From cebef9011879b7d969f0b0bd160b74ff3b705877 Mon Sep 17 00:00:00 2001 From: bQUARKz Date: Tue, 5 May 2026 11:12:37 +0100 Subject: [PATCH 01/37] implements PLN-0062 --- discussion/index.ndjson | 3 +- ...034-vscode-editor-migration-feasibility.md | 106 +++ ...EC-0031-studio-editor-workspace-cleanup.md | 148 ++++ ...-and-state-cleanup-after-editor-removal.md | 91 ++ ...odule-removal-with-runtime-preservation.md | 92 ++ ...lesson-cleanup-for-editor-stack-removal.md | 91 ++ .../src/main/java/p/studio/AppContainer.java | 18 - .../src/main/java/p/studio/Container.java | 14 - .../projectsessions/StudioProjectSession.java | 44 +- .../StudioProjectSessionFactory.java | 26 +- .../projectstate/ProjectLocalStudioState.java | 121 +-- .../main/java/p/studio/window/MainView.java | 16 +- .../window/StudioWindowCoordinator.java | 4 +- .../java/p/studio/workspaces/WorkspaceId.java | 1 - .../editor/EditorDocumentHighlightOwner.java | 6 - .../EditorDocumentHighlightingResult.java | 20 - .../EditorDocumentHighlightingRouter.java | 32 - .../EditorDocumentInlineHintRouter.java | 20 - .../editor/EditorDocumentPresentation.java | 30 - .../EditorDocumentPresentationRegistry.java | 122 --- .../EditorDocumentPresentationStyles.java | 28 - ...ditorDocumentScopeGuideGraphicFactory.java | 91 -- .../editor/EditorDocumentScopeGuideModel.java | 340 -------- .../workspaces/editor/EditorHelperPanel.java | 96 --- .../editor/EditorInlineHintLayout.java | 72 -- .../editor/EditorInlineHintOverlay.java | 124 --- .../editor/EditorInlineHintProjection.java | 159 ---- .../editor/EditorOpenFileBuffer.java | 37 - .../editor/EditorOpenFileSession.java | 112 --- .../workspaces/editor/EditorOutlinePanel.java | 116 --- .../editor/EditorProjectNavigatorPanel.java | 337 -------- .../workspaces/editor/EditorStatusBar.java | 218 ----- .../workspaces/editor/EditorTabStrip.java | 252 ------ .../workspaces/editor/EditorWarningStrip.java | 103 --- .../workspaces/editor/EditorWorkspace.java | 784 ------------------ .../editor/EditorWorkspaceIcons.java | 85 -- .../EditorDocumentHighlightToken.java | 25 - .../EditorDocumentSemanticHighlighting.java | 64 -- .../EditorDocumentSyntaxHighlighting.java | 59 -- .../EditorDocumentSyntaxHighlightingBash.java | 28 - .../EditorDocumentSyntaxHighlightingJson.java | 22 - ...orDocumentSyntaxHighlightingPlainText.java | 9 - .../StudioProjectSessionFactoryTest.java | 111 +-- .../StudioProjectSessionTest.java | 99 +-- .../ProjectLocalStudioStateServiceTest.java | 53 +- .../EditorDocumentHighlightingRouterTest.java | 315 ------- ...ditorDocumentPresentationRegistryTest.java | 60 -- .../EditorDocumentScopeGuideModelTest.java | 166 ---- .../editor/EditorInlineHintLayoutTest.java | 44 - .../editor/EditorOpenFileSessionTest.java | 140 ---- 50 files changed, 591 insertions(+), 4563 deletions(-) create mode 100644 discussion/workflow/agendas/AGD-0034-vscode-editor-migration-feasibility.md create mode 100644 discussion/workflow/decisions/DEC-0031-studio-editor-workspace-cleanup.md create mode 100644 discussion/workflow/plans/PLN-0062-shell-session-and-state-cleanup-after-editor-removal.md create mode 100644 discussion/workflow/plans/PLN-0063-legacy-lsp-and-vfs-module-removal-with-runtime-preservation.md create mode 100644 discussion/workflow/plans/PLN-0064-normative-test-and-lesson-cleanup-for-editor-stack-removal.md delete mode 100644 prometeu-studio/src/main/java/p/studio/workspaces/editor/EditorDocumentHighlightOwner.java delete mode 100644 prometeu-studio/src/main/java/p/studio/workspaces/editor/EditorDocumentHighlightingResult.java delete mode 100644 prometeu-studio/src/main/java/p/studio/workspaces/editor/EditorDocumentHighlightingRouter.java delete mode 100644 prometeu-studio/src/main/java/p/studio/workspaces/editor/EditorDocumentInlineHintRouter.java delete mode 100644 prometeu-studio/src/main/java/p/studio/workspaces/editor/EditorDocumentPresentation.java delete mode 100644 prometeu-studio/src/main/java/p/studio/workspaces/editor/EditorDocumentPresentationRegistry.java delete mode 100644 prometeu-studio/src/main/java/p/studio/workspaces/editor/EditorDocumentPresentationStyles.java delete mode 100644 prometeu-studio/src/main/java/p/studio/workspaces/editor/EditorDocumentScopeGuideGraphicFactory.java delete mode 100644 prometeu-studio/src/main/java/p/studio/workspaces/editor/EditorDocumentScopeGuideModel.java delete mode 100644 prometeu-studio/src/main/java/p/studio/workspaces/editor/EditorHelperPanel.java delete mode 100644 prometeu-studio/src/main/java/p/studio/workspaces/editor/EditorInlineHintLayout.java delete mode 100644 prometeu-studio/src/main/java/p/studio/workspaces/editor/EditorInlineHintOverlay.java delete mode 100644 prometeu-studio/src/main/java/p/studio/workspaces/editor/EditorInlineHintProjection.java delete mode 100644 prometeu-studio/src/main/java/p/studio/workspaces/editor/EditorOpenFileBuffer.java delete mode 100644 prometeu-studio/src/main/java/p/studio/workspaces/editor/EditorOpenFileSession.java delete mode 100644 prometeu-studio/src/main/java/p/studio/workspaces/editor/EditorOutlinePanel.java delete mode 100644 prometeu-studio/src/main/java/p/studio/workspaces/editor/EditorProjectNavigatorPanel.java delete mode 100644 prometeu-studio/src/main/java/p/studio/workspaces/editor/EditorStatusBar.java delete mode 100644 prometeu-studio/src/main/java/p/studio/workspaces/editor/EditorTabStrip.java delete mode 100644 prometeu-studio/src/main/java/p/studio/workspaces/editor/EditorWarningStrip.java delete mode 100644 prometeu-studio/src/main/java/p/studio/workspaces/editor/EditorWorkspace.java delete mode 100644 prometeu-studio/src/main/java/p/studio/workspaces/editor/EditorWorkspaceIcons.java delete mode 100644 prometeu-studio/src/main/java/p/studio/workspaces/editor/syntaxhighlight/EditorDocumentHighlightToken.java delete mode 100644 prometeu-studio/src/main/java/p/studio/workspaces/editor/syntaxhighlight/EditorDocumentSemanticHighlighting.java delete mode 100644 prometeu-studio/src/main/java/p/studio/workspaces/editor/syntaxhighlight/EditorDocumentSyntaxHighlighting.java delete mode 100644 prometeu-studio/src/main/java/p/studio/workspaces/editor/syntaxhighlight/EditorDocumentSyntaxHighlightingBash.java delete mode 100644 prometeu-studio/src/main/java/p/studio/workspaces/editor/syntaxhighlight/EditorDocumentSyntaxHighlightingJson.java delete mode 100644 prometeu-studio/src/main/java/p/studio/workspaces/editor/syntaxhighlight/EditorDocumentSyntaxHighlightingPlainText.java delete mode 100644 prometeu-studio/src/test/java/p/studio/workspaces/editor/EditorDocumentHighlightingRouterTest.java delete mode 100644 prometeu-studio/src/test/java/p/studio/workspaces/editor/EditorDocumentPresentationRegistryTest.java delete mode 100644 prometeu-studio/src/test/java/p/studio/workspaces/editor/EditorDocumentScopeGuideModelTest.java delete mode 100644 prometeu-studio/src/test/java/p/studio/workspaces/editor/EditorInlineHintLayoutTest.java delete mode 100644 prometeu-studio/src/test/java/p/studio/workspaces/editor/EditorOpenFileSessionTest.java diff --git a/discussion/index.ndjson b/discussion/index.ndjson index 1c6ed076..a0100ba9 100644 --- a/discussion/index.ndjson +++ b/discussion/index.ndjson @@ -1,4 +1,5 @@ -{"type":"meta","next_id":{"DSC":31,"AGD":34,"DEC":31,"PLN":62,"LSN":47,"CLSN":1}} +{"type":"meta","next_id":{"DSC":32,"AGD":35,"DEC":32,"PLN":65,"LSN":47,"CLSN":1}} +{"type":"discussion","id":"DSC-0031","status":"in_progress","ticket":"studio-editor-workspace-cleanup","title":"Limpeza completa do Workspace Editor do Studio e remoção dos acoplamentos legados","created_at":"2026-05-05","updated_at":"2026-05-05","tags":["studio","editor","cleanup","vfs","lsp","migration"],"agendas":[{"id":"AGD-0034","file":"AGD-0034-vscode-editor-migration-feasibility.md","status":"accepted","created_at":"2026-05-05","updated_at":"2026-05-05"}],"decisions":[{"id":"DEC-0031","file":"DEC-0031-studio-editor-workspace-cleanup.md","status":"in_progress","created_at":"2026-05-05","updated_at":"2026-05-05","ref_agenda":"AGD-0034"}],"plans":[{"id":"PLN-0062","file":"PLN-0062-shell-session-and-state-cleanup-after-editor-removal.md","status":"done","created_at":"2026-05-05","updated_at":"2026-05-05","ref_decisions":["DEC-0031"]},{"id":"PLN-0063","file":"PLN-0063-legacy-lsp-and-vfs-module-removal-with-runtime-preservation.md","status":"open","created_at":"2026-05-05","updated_at":"2026-05-05","ref_decisions":["DEC-0031"]},{"id":"PLN-0064","file":"PLN-0064-normative-test-and-lesson-cleanup-for-editor-stack-removal.md","status":"open","created_at":"2026-05-05","updated_at":"2026-05-05","ref_decisions":["DEC-0031"]}],"lessons":[]} {"type":"discussion","id":"DSC-0030","status":"done","ticket":"studio-scene-pack-runtime-binary-contract","title":"Studio scene pack contract for runtime SCENE binary payload","created_at":"2026-04-24","updated_at":"2026-05-01","tags":["studio","packer","runtime","scene","asset-pack","binary-format","tiled"],"agendas":[],"decisions":[],"plans":[],"lessons":[{"id":"LSN-0046","file":"discussion/lessons/DSC-0030-studio-scene-pack-runtime-binary-contract/LSN-0046-canonical-scene-owns-editorial-truth-while-pack-stays-request-driven.md","status":"done","created_at":"2026-05-01","updated_at":"2026-05-01"}]} {"type":"discussion","id":"DSC-0029","status":"done","ticket":"studio-frame-composer-syscall-and-sprite-alignment","title":"Studio Alignment with Runtime FrameComposer Syscalls and Sprite Composition","created_at":"2026-04-18","updated_at":"2026-04-18","tags":["studio","compiler","pbs","stdlib","runtime-alignment","abi","syscall","frame-composer","sprites"],"agendas":[],"decisions":[],"plans":[],"lessons":[{"id":"LSN-0041","file":"discussion/lessons/DSC-0029-studio-frame-composer-syscall-and-sprite-alignment/LSN-0041-composer-must-own-public-sprite-composition.md","status":"done","created_at":"2026-04-18","updated_at":"2026-04-18"}]} {"type":"discussion","id":"DSC-0028","status":"done","ticket":"studio-tiled-parser-assets-scene-asset-type","title":"Tiled Parser and Scene Asset-Type Ownership in Assets Workspace","created_at":"2026-04-15","updated_at":"2026-04-23","tags":["studio","assets","scene","tiled","parser","asset-type"],"agendas":[],"decisions":[],"plans":[],"lessons":[{"id":"LSN-0045","file":"discussion/lessons/DSC-0028-studio-tiled-parser-assets-scene-asset-type/LSN-0045-asset-owned-scene-bank-and-tiled-xml-workflow.md","status":"done","created_at":"2026-04-23","updated_at":"2026-04-23"}]} diff --git a/discussion/workflow/agendas/AGD-0034-vscode-editor-migration-feasibility.md b/discussion/workflow/agendas/AGD-0034-vscode-editor-migration-feasibility.md new file mode 100644 index 00000000..79011aab --- /dev/null +++ b/discussion/workflow/agendas/AGD-0034-vscode-editor-migration-feasibility.md @@ -0,0 +1,106 @@ +--- +id: AGD-0034 +ticket: studio-editor-workspace-cleanup +title: Limpeza completa do Workspace Editor do Studio e remoção dos acoplamentos legados +status: accepted +created: 2026-05-05 +resolved: 2026-05-05 +decision: DEC-0031 +tags: [studio, editor, cleanup, vfs, lsp, migration] +--- + +## Pain + +O repositório ainda carrega um `Workspace Editor` no `prometeu-studio` junto com camadas de `VFS` e `LSP` desenhadas especificamente para esse editor embutido. + +Esse conjunto virou um legado arquitetural: + +- o editor JavaFX não é mais a direção do produto; +- o `prometeu-vfs` atual está acoplado ao modelo editorial do editor embutido; +- o `prometeu-lsp` atual está acoplado ao `VFS` e ao host local do Studio; +- e manter essa base viva só aumenta o custo da futura reconstrução correta do backend de código. + +## Context + +- O monorepo já separa `prometeu-compiler`, `prometeu-packer` e `prometeu-studio`, mas o `prometeu-lsp` e o `prometeu-vfs` atuais nasceram como suporte ao editor embutido. +- A capacidade de compilação dos projetos deve continuar existindo no Studio. +- O alvo imediato não é discutir o novo LSP nem o novo contrato de automação. +- O alvo imediato é remover: + - o `Workspace Editor`; + - o `prometeu-lsp` legado usado por ele; + - e o `prometeu-vfs` acoplado a esse modelo editorial. +- O Studio continua existindo como produto fora do editor: + - shell e launcher de projeto; + - assets workspace; + - shipper/build surfaces; + - play/stop e integração com runtime/debug. +- Uma agenda futura poderá discutir a reconstrução do backend de código e do novo servidor LSP, mas isso fica fora deste artefato. + +## Open Questions + +- Quais partes do `prometeu-vfs` atual pertencem exclusivamente ao `Workspace Editor` e podem ser removidas integralmente? +- Existe algum consumer ainda válido do `prometeu-lsp` legado fora do editor embutido? +- O fluxo `play` ou qualquer outro fluxo do Studio depende hoje, mesmo indiretamente, de APIs do editor legado, do `VFS` legado ou do `LSP` legado? +- A limpeza deve remover apenas código de produção ou também specs, testes, lessons e referências que tratam o editor embutido como superfície ativa? +- Quais contratos de compilação precisam ser preservados explicitamente enquanto a camada de edição é removida? + +## Options + +### Option A - Manter o editor legado até a reconstrução completa do backend de código +- **Approach:** adiar a limpeza e preservar temporariamente `Workspace Editor`, `prometeu-vfs` legado e `prometeu-lsp` legado até o novo backend existir. +- **Pro:** menor ruptura imediata. +- **Con:** prolonga a vida do legado, aumenta custo de manutenção e deixa a futura reconstrução mais confusa. +- **Maintainability:** fraca. + +### Option B - Limpeza completa agora, preservando apenas a compilação do Studio +- **Approach:** remover `Workspace Editor`, `prometeu-lsp` legado e o `prometeu-vfs` acoplado a esse modelo, mantendo apenas as superfícies de compilação e execução que não dependem desse stack. +- **Pro:** reduz o legado antes da reconstrução, clarifica boundaries e impede que o futuro LSP nasça comprometido por compatibilidade acidental. +- **Con:** cria um período sem editor embutido e sem backend de código novo dentro do Studio. +- **Maintainability:** forte. + +Vamos de Option B. + +## Discussion + +O trabalho desta agenda não é desenhar o novo backend de código. + +O trabalho desta agenda é remover o legado que impediria esse redesenho. + +Isso implica alguns cortes diretos: + +- o `Workspace Editor` deixa de ser superfície ativa do Studio; +- o `prometeu-lsp` atual deixa de ser tratado como base evolutiva; +- o `prometeu-vfs` atual, por ser acoplado ao modelo editorial do editor embutido, sai junto com esse stack; +- as capacidades de compilação, build e execução que não dependem desse stack devem ser preservadas. + +O princípio aqui é de limpeza arquitetural antes de reconstrução: + +- não carregar compatibilidade acidental com o editor antigo; +- não manter um `VFS` ou `LSP` cujo contrato nasce de um modelo que já foi abandonado; +- e não misturar, nesta discussão, a limpeza do legado com o desenho do futuro servidor LSP. + +Isso também reduz o risco de falsa migração: + +- em vez de adaptar o editor atual, o repositório assume explicitamente que ele vai morrer; +- em vez de reaproveitar um `LSP` embrionário acoplado ao host local, o repositório aceita que um novo backend de código será desenhado depois; +- e em vez de preservar o `VFS` por inércia, o repositório valida se ele ainda possui valor fora do modelo que o originou. + +## Resolution + +Recomendação preliminar: + +- seguir com a Option B; +- tratar esta agenda exclusivamente como limpeza completa do `Workspace Editor` do Studio; +- remover junto o `prometeu-lsp` legado e o `prometeu-vfs` acoplado a esse modelo; +- preservar explicitamente a capacidade de compilação e os fluxos do Studio que não dependem desse stack; +- e abrir uma discussão futura separada para o backend de código novo, o novo LSP e o contrato de automação. + +## Next Step + +Se a direção fizer sentido, o próximo passo disciplinado é fechar uma `decision` com: + +1. o escopo exato da remoção do `Workspace Editor`; +2. o escopo exato da remoção do `prometeu-lsp` legado; +3. o escopo exato da remoção do `prometeu-vfs` acoplado a esse modelo; +4. as capacidades de compilação e execução que devem sobreviver intactas; +5. e os artefatos normativos, testes e código que precisam ser limpos ou preservados. diff --git a/discussion/workflow/decisions/DEC-0031-studio-editor-workspace-cleanup.md b/discussion/workflow/decisions/DEC-0031-studio-editor-workspace-cleanup.md new file mode 100644 index 00000000..44777193 --- /dev/null +++ b/discussion/workflow/decisions/DEC-0031-studio-editor-workspace-cleanup.md @@ -0,0 +1,148 @@ +--- +id: DEC-0031 +ticket: studio-editor-workspace-cleanup +title: Limpeza completa do Workspace Editor do Studio e remoção dos acoplamentos legados +status: in_progress +created: 2026-05-05 +accepted: 2026-05-05 +agenda: AGD-0034 +plans: [PLN-0062, PLN-0063, PLN-0064] +tags: [studio, editor, cleanup, vfs, lsp, migration] +--- + +## Decision + +O repositório SHALL remover integralmente o `Workspace Editor` do Studio como superfície ativa do produto. + +Essa remoção SHALL incluir: + +1. o workspace de código embutido em `prometeu-studio`; +2. o `prometeu-lsp` legado usado por esse workspace; +3. o `prometeu-vfs` legado acoplado ao modelo editorial desse workspace; +4. os pontos de integração do shell, da sessão de projeto e do bootstrap que assumem a existência desse stack; +5. e os artefatos normativos, testes e referências documentais que tratam esse stack como superfície vigente. + +Ao mesmo tempo, esta decisão ALSO locks que: + +1. a capacidade de compilação dos projetos MUST permanecer disponível no Studio; +2. os fluxos atuais de `build`, `play`, `run` e `debug` MUST permanecer funcionais desde que não dependam do editor legado, do `prometeu-lsp` legado ou do `prometeu-vfs` legado; +3. esta decisão MUST NOT introduzir o novo backend de código, o novo servidor LSP ou o futuro contrato de automação; +4. qualquer reconstrução dessas superfícies MUST acontecer em discussão posterior e separada. + +## Rationale + +O `Workspace Editor`, o `prometeu-lsp` atual e o `prometeu-vfs` atual formam um stack único, criado especificamente para o editor embutido do Studio. + +Esse stack não é mais alinhado à direção do produto: + +1. o editor JavaFX deixou de ser a direção principal; +2. o `prometeu-lsp` atual não deve ser tratado como base séria para um futuro servidor LSP; +3. o `prometeu-vfs` atual carrega um contrato editorial pensado para o editor embutido; +4. manter esse legado vivo aumenta o custo de reconstrução e preserva boundaries errados por inércia. + +Portanto, a limpeza precisa acontecer antes da reconstrução. + +## Technical Specification + +### 1. Editor Workspace Removal + +O Studio MUST remover a superfície `Code Editor` do shell. + +Isso inclui: + +1. remover `WorkspaceId.EDITOR`; +2. remover o `EditorWorkspace` e todos os controles, painéis, modelos e helpers sob `prometeu-studio/.../workspaces/editor`; +3. remover a presença do editor na workspace rail, no layout principal e no fluxo de restauração de shell; +4. remover strings, ícones e estado visual exclusivos dessa superfície. + +### 2. Legacy LSP Removal + +O repositório MUST remover o `prometeu-lsp` legado como módulo ativo. + +Isso inclui: + +1. remover os módulos `prometeu-lsp-api` e `prometeu-lsp-v1`; +2. remover `LspService`, `LspServiceFactory` e todos os DTOs/messages específicos desse stack legado; +3. remover a criação e injeção dessas dependências no `AppContainer`, no `Container`, na sessão de projeto e nos testes associados; +4. remover a hipótese de que esse `LSP` será evoluído para o futuro backend de código. + +Os conceitos úteis descobertos nesse stack MAY ser reaproveitados mais tarde, mas esta decisão não preserva compatibilidade de código, pacote ou contrato com ele. + +### 3. Legacy VFS Removal + +O repositório MUST remover o `prometeu-vfs` legado como módulo ativo. + +Isso inclui: + +1. remover os módulos `prometeu-vfs-api` e `prometeu-vfs-v1`; +2. remover `VfsProjectDocument`, `ProjectDocumentVfsFactory` e implementações filesystem-backed associadas; +3. remover a criação e posse desse `VFS` na sessão de projeto; +4. remover qualquer regra que trate esse `VFS` como boundary documental vigente do Studio. + +Esta decisão assume que o `prometeu-vfs` atual pertence ao modelo do editor legado e, portanto, não deve sobreviver por compatibilidade acidental. + +### 4. Session and Shell Cleanup + +O Studio MUST reconfigurar a sessão de projeto e o shell principal para não depender do stack removido. + +Isso inclui: + +1. remover `LSP` e `VFS` legados da estrutura de `StudioProjectSession`; +2. remover sua criação em `StudioProjectSessionFactory`; +3. remover dependências globais correspondentes do bootstrap e do container; +4. remover persistência de layout e restauração editorial específicas do editor. + +### 5. State Cleanup + +O estado local do projeto MUST deixar de persistir dados exclusivos do editor legado. + +Isso inclui: + +1. remover `editorRestoration`; +2. remover `shellLayout.editorLayout`; +3. garantir fallback seguro para estados antigos já persistidos em `.studio/state.json`; +4. preservar apenas os campos ainda pertencentes a workspaces vivos e ao shell remanescente. + +### 6. Documentation and Test Cleanup + +O repositório MUST limpar artefatos normativos e testes que descrevem o stack legado como vigente. + +Isso inclui: + +1. revisar ou remover as specs do `Code Editor`, do `Project Document VFS` e do `Integrated LSP Semantic Read Phase`; +2. revisar `docs/specs/studio/README.md`; +3. remover ou arquivar testes exclusivos do editor, do `prometeu-lsp` legado e do `prometeu-vfs` legado; +4. revisar lessons e referências históricas para deixar explícito que se tratam de legado, quando forem mantidas. + +### 7. Capabilities That MUST Survive + +As seguintes capacidades MUST sobreviver a esta limpeza: + +1. compilação de projetos pelo pipeline canônico existente; +2. build de artefatos via `BuilderPipelineService`; +3. preparação do fluxo de shipper; +4. `play`, `run` e `debug` do Studio, desde que apoiados nas superfícies remanescentes e não no stack removido; +5. workspaces `Assets`, `Shipper` e `Debug`, além do launcher e do shell geral. + +### 8. Explicit Non-Goals + +Esta decisão MUST NOT: + +1. definir o novo servidor LSP; +2. definir o novo contrato de automação; +3. definir o novo modelo de sessão de código; +4. definir integração com VS Code; +5. reter compatibilidade com o `LSP` ou `VFS` legados por conveniência. + +## Constraints + +1. A limpeza MUST preservar o pipeline canônico `analyze`, `compile` e `build` já existente no compiler. +2. A limpeza MUST evitar remover ou degradar fluxos de `build/run/debug` que hoje dependem apenas de `compiler`, `shipper`, runtime e shell. +3. A limpeza MUST deixar o shell do Studio em estado coerente, sem workspace fantasma, sem layout órfão e sem dependências mortas. +4. A limpeza MUST tratar specs e estado persistido como parte do trabalho, não como detalhe pós-código. +5. A futura reconstrução do backend de código SHALL nascer em discussão separada, sem herdar obrigação de compatibilidade com o stack removido. + +## Revision Log + +- 2026-05-05: Initial draft from AGD-0034. +- 2026-05-05: Accepted and decomposed into PLN-0062, PLN-0063, and PLN-0064. diff --git a/discussion/workflow/plans/PLN-0062-shell-session-and-state-cleanup-after-editor-removal.md b/discussion/workflow/plans/PLN-0062-shell-session-and-state-cleanup-after-editor-removal.md new file mode 100644 index 00000000..31268083 --- /dev/null +++ b/discussion/workflow/plans/PLN-0062-shell-session-and-state-cleanup-after-editor-removal.md @@ -0,0 +1,91 @@ +--- +id: PLN-0062 +ticket: studio-editor-workspace-cleanup +title: Shell Session and State Cleanup After Editor Removal +status: done +created: 2026-05-05 +completed: 2026-05-05 +tags: [studio, editor, cleanup, shell, session, state] +--- + +## Objective + +Remove the `Code Editor` workspace from the Studio shell and reconfigure project session and persisted state so the application remains coherent without any editor-owned concepts. + +## Background + +`DEC-0031` locks the complete removal of the embedded editor stack. The shell, project session, workspace registry, and `.studio/state.json` currently still assume the existence of `WorkspaceId.EDITOR`, `EditorWorkspace`, editor restoration state, and editor-specific layout state. + +## Scope + +### Included +- Remove `WorkspaceId.EDITOR` from the Studio shell. +- Remove `EditorWorkspace` registration and shell integration. +- Remove editor-specific state persistence and restoration paths. +- Remove `LSP`/`VFS` legacy ownership from `StudioProjectSession` and `StudioProjectSessionFactory`. +- Keep `Assets`, `Shipper`, `Debug`, launcher, and shell flows functional. + +### Excluded +- Removal of the `prometeu-lsp` and `prometeu-vfs` module source trees themselves. +- Documentation and lesson cleanup. +- New code backend or replacement LSP architecture. + +## Execution Steps + +### Step 1 - Remove editor workspace registration from the shell + +**What:** Remove all shell-level references to the `Code Editor` workspace. +**How:** Update the main window composition to stop creating `EditorWorkspace`, remove the editor rail item, stop selecting or restoring `WorkspaceId.EDITOR`, and ensure shell fallback remains stable when old persisted state still references the editor. +**File(s):** `prometeu-studio/src/main/java/p/studio/window/MainView.java`, `prometeu-studio/src/main/java/p/studio/workspaces/WorkspaceId.java`, any directly related shell controls or selectors. + +### Step 2 - Remove editor-owned state and restoration from project-local state + +**What:** Remove editor layout and restoration data from persisted project-local Studio state. +**How:** Simplify `ProjectLocalStudioState` to remove `editorRestoration` and `shellLayout.editorLayout`, update normalization/defaults, and make loading old `.studio/state.json` degrade safely without crashes or stale editor assumptions. +**File(s):** `prometeu-studio/src/main/java/p/studio/projectstate/ProjectLocalStudioState.java`, `prometeu-studio/src/main/java/p/studio/projectstate/ProjectLocalStudioStateService.java`, any callers that write or restore editor state. + +### Step 3 - Reconfigure project session to stop owning editor legacy dependencies + +**What:** Remove legacy editor-driven `LSP` and `VFS` ownership from project session composition. +**How:** Refactor `StudioProjectSession` and `StudioProjectSessionFactory` so opening a project no longer constructs `VfsProjectDocument` or `LspService`, and so close semantics remain valid without those resources. +**File(s):** `prometeu-studio/src/main/java/p/studio/projectsessions/StudioProjectSession.java`, `prometeu-studio/src/main/java/p/studio/projectsessions/StudioProjectSessionFactory.java`, dependent tests. + +### Step 4 - Remove bootstrap/container dependencies that only existed for the editor stack + +**What:** Remove application bootstrap and container seams that exist only to inject legacy editor stack services. +**How:** Delete `LspServiceFactory` and `ProjectDocumentVfsFactory` accessors from the container surfaces once shell/session no longer depend on them, and update `AppContainer` accordingly. +**File(s):** `prometeu-studio/src/main/java/p/studio/Container.java`, `prometeu-app/src/main/java/p/studio/AppContainer.java`, directly affected tests. + +## Test Requirements + +### Unit Tests +- Update session and state tests to reflect the absence of editor state. +- Add coverage for loading old persisted project-local state without editor restoration fields being required. + +### Integration Tests +- Verify the main Studio shell opens a project and activates a surviving workspace without editor registration. +- Verify session close still saves valid project-local state and shuts down surviving services cleanly. + +### Manual Verification +- Open the Studio shell and confirm only surviving workspaces appear. +- Reopen a project with stale `.studio/state.json` containing editor data and confirm safe fallback. +- Confirm project switching and shell startup remain stable. + +## Acceptance Criteria + +- [x] `WorkspaceId.EDITOR` no longer exists in production code. +- [x] `MainView` no longer instantiates or restores `EditorWorkspace`. +- [x] Project-local state no longer persists editor restoration or editor layout fields. +- [x] `StudioProjectSession` no longer owns legacy editor `LSP`/`VFS` resources. +- [x] The Studio shell remains functional with surviving workspaces. + +## Dependencies + +- `DEC-0031` accepted and normatively locked. +- Knowledge of all shell/session/state call sites that currently assume the editor exists. + +## Risks + +- Shell restoration may break if old persisted state is not normalized defensively. +- Session teardown may regress if hidden resource ownership remains after field removal. +- Removing editor assumptions too early may temporarily orphan callers still using editor-specific state APIs. diff --git a/discussion/workflow/plans/PLN-0063-legacy-lsp-and-vfs-module-removal-with-runtime-preservation.md b/discussion/workflow/plans/PLN-0063-legacy-lsp-and-vfs-module-removal-with-runtime-preservation.md new file mode 100644 index 00000000..1429643b --- /dev/null +++ b/discussion/workflow/plans/PLN-0063-legacy-lsp-and-vfs-module-removal-with-runtime-preservation.md @@ -0,0 +1,92 @@ +--- +id: PLN-0063 +ticket: studio-editor-workspace-cleanup +title: Legacy LSP and VFS Module Removal with Runtime Preservation +status: open +created: 2026-05-05 +completed: +tags: [studio, editor, cleanup, lsp, vfs, runtime] +--- + +## Objective + +Remove the legacy `prometeu-lsp` and `prometeu-vfs` modules and all remaining code references to them while preserving compiler, shipper, play, run, and debug flows that do not depend on the editor stack. + +## Background + +`DEC-0031` treats the current `prometeu-lsp` and `prometeu-vfs` modules as part of the embedded editor legacy stack. The Studio execution path must continue to compile, build, package, and run projects through the existing compiler and runtime orchestration layers. + +## Scope + +### Included +- Remove `prometeu-lsp` modules from Gradle settings and codebase references. +- Remove `prometeu-vfs` modules from Gradle settings and codebase references. +- Remove tests dedicated to these legacy modules. +- Verify `StudioShipperService`, `StudioPlayStopCoordinator`, and runtime/debug flows remain intact. + +### Excluded +- Shell/editor state cleanup handled by a separate plan. +- Documentation/spec/lesson cleanup handled by a separate plan. +- New replacement backend services. + +## Execution Steps + +### Step 1 - Remove Gradle module registration for legacy editor stack modules + +**What:** Stop building the legacy `prometeu-lsp` and `prometeu-vfs` modules. +**How:** Remove the module includes and any direct module dependencies that point to `prometeu-lsp:*` and `prometeu-vfs:*`, then fix resulting build graph fallout in Studio modules. +**File(s):** `settings.gradle.kts`, affected `build.gradle.kts` files in `prometeu-app`, `prometeu-studio`, and module directories. + +### Step 2 - Remove legacy module source trees and direct test coverage + +**What:** Delete the legacy `prometeu-lsp` and `prometeu-vfs` code once all consumers are detached. +**How:** Remove module source files and their dedicated tests only after production call sites no longer compile against them. +**File(s):** `prometeu-lsp/**`, `prometeu-vfs/**`, related test sources in `prometeu-studio`. + +### Step 3 - Preserve compiler and shipper build flow + +**What:** Ensure build preparation still uses the canonical compiler pipeline without editor legacy dependencies. +**How:** Validate and adjust `StudioShipperService` and any shipper/build callers so they continue using `BuilderPipelineService`, `BuilderPipelineConfig`, and `BuilderPipelineContext` directly without reintroducing removed editor-layer seams. +**File(s):** `prometeu-studio/src/main/java/p/studio/shipper/StudioShipperService.java`, affected compiler/shipper integration tests. + +### Step 4 - Preserve play, run, and debug execution flow + +**What:** Ensure runtime orchestration continues to function after legacy module removal. +**How:** Re-test and patch `StudioPlayStopCoordinator`, runtime handshake services, execution session handling, and debug workspace projections if any hidden import or event dependency pointed at removed editor-stack modules. +**File(s):** `prometeu-studio/src/main/java/p/studio/execution/StudioPlayStopCoordinator.java`, `prometeu-studio/src/main/java/p/studio/debug/runtime/**`, `prometeu-studio/src/main/java/p/studio/workspaces/debug/**`, related tests. + +## Test Requirements + +### Unit Tests +- Update or remove module-specific tests for `prometeu-lsp` and `prometeu-vfs`. +- Preserve unit coverage for execution session, play/stop coordination, and runtime handshake behavior. + +### Integration Tests +- Run compiler pipeline integration tests that cover `analyze`, `compile`, and `build`. +- Run shipper/build integration tests that exercise `StudioShipperService`. +- Run runtime/debug integration or coordinator tests that validate play/stop behavior. + +### Manual Verification +- Trigger Studio build flow and confirm artifact generation still works. +- Trigger Studio play flow and confirm runtime launch/stop still works. +- Open Debug and Shipper workspaces and confirm they remain operational. + +## Acceptance Criteria + +- [ ] `prometeu-lsp` is no longer part of the build graph. +- [ ] `prometeu-vfs` is no longer part of the build graph. +- [ ] No production Studio class imports legacy `LSP` or `VFS` module types. +- [ ] Compiler and shipper build flows still work. +- [ ] Play/run/debug flows still work without the removed modules. + +## Dependencies + +- `DEC-0031` accepted and normatively locked. +- Shell/session cleanup completed enough that no surviving production code still requires legacy `LSP`/`VFS` types. + +## Risks + +- Hidden transitive dependencies may keep the build graph coupled to removed modules longer than expected. +- Runtime or debug flows may have indirect event or session assumptions not obvious from imports alone. +- Deleting modules too early may obscure compile errors that should instead be fixed in surviving Studio code first. + diff --git a/discussion/workflow/plans/PLN-0064-normative-test-and-lesson-cleanup-for-editor-stack-removal.md b/discussion/workflow/plans/PLN-0064-normative-test-and-lesson-cleanup-for-editor-stack-removal.md new file mode 100644 index 00000000..1572f13a --- /dev/null +++ b/discussion/workflow/plans/PLN-0064-normative-test-and-lesson-cleanup-for-editor-stack-removal.md @@ -0,0 +1,91 @@ +--- +id: PLN-0064 +ticket: studio-editor-workspace-cleanup +title: Normative Test and Lesson Cleanup for Editor Stack Removal +status: open +created: 2026-05-05 +completed: +tags: [studio, editor, cleanup, docs, tests, lessons] +--- + +## Objective + +Remove or revise the normative documentation, tests, lessons, and user-facing resources that describe the embedded editor stack as a current Studio surface. + +## Background + +`DEC-0031` treats the editor stack removal as both code cleanup and normative cleanup. The repository currently contains active specs, README entries, i18n resources, and lessons that define `Code Editor`, `prometeu-vfs`, and the integrated semantic-read phase as active architecture. + +## Scope + +### Included +- Remove or rewrite Studio specs dedicated to the embedded editor stack. +- Update the Studio specs index and README. +- Remove or archive editor/LSP/VFS-specific tests that are no longer valid. +- Reclassify legacy lessons and references so they are not presented as active guidance. +- Remove user-facing i18n strings that only existed for the editor stack. + +### Excluded +- Implementation of shell/session/module cleanup itself. +- Future specs for the replacement backend or replacement external-editor strategy. + +## Execution Steps + +### Step 1 - Clean normative Studio specs + +**What:** Remove or replace specs that define the embedded editor stack as active architecture. +**How:** Delete or explicitly retire the `Code Editor`, `Project Document VFS`, and `Integrated LSP Semantic Read Phase` specs, then rewrite any remaining Studio README/index material so it no longer points to dead architecture. +**File(s):** `docs/specs/studio/5. Code Editor Workspace Specification.md`, `docs/specs/studio/6. Project Document VFS Specification.md`, `docs/specs/studio/7. Integrated LSP Semantic Read Phase Specification.md`, `docs/specs/studio/README.md`. + +### Step 2 - Clean user-facing resources and shell references + +**What:** Remove editor-specific strings, labels, and messages that no longer correspond to product surfaces. +**How:** Delete `workspace.code` and `codeEditor.*` message keys and any equivalent theme or resource references still tied to removed editor UI. +**File(s):** `prometeu-studio/src/main/resources/i18n/messages.properties`, any directly related theme or resource files. + +### Step 3 - Clean tests and update surviving expectations + +**What:** Remove tests whose sole purpose was validating the editor stack and update remaining tests to stop expecting that stack. +**How:** Delete or rewrite tests for editor workspace behavior, legacy `LSP`, legacy `VFS`, session expectations, and any shell assertions that still require the editor workspace. +**File(s):** `prometeu-studio/src/test/java/p/studio/projectsessions/**`, editor-related tests, `prometeu-lsp/**/test/**`, `prometeu-vfs/**/test/**`, any shell-level tests affected by workspace removal. + +### Step 4 - Reclassify lessons and historical references + +**What:** Ensure discussion lessons remain historically useful without being mistaken for current architecture. +**How:** Review the lessons and references tied to editor/VFS/LSP waves and either archive them, mark them as legacy, or update index/readme material so they are not treated as active operational guidance. +**File(s):** affected files under `discussion/lessons/DSC-0010*`, `DSC-0012*`, `DSC-0013*`, `DSC-0014*`, `DSC-0016*`, `DSC-0017*`, `DSC-0020*`, `DSC-0021*`, plus any summary/index surfaces that present them. + +## Test Requirements + +### Unit Tests +- Ensure no surviving test suite still references removed editor stack types or message keys. +- Add assertions where needed that remaining shell/resource state is internally consistent. + +### Integration Tests +- Validate the Studio docs/spec tree remains internally linked after removal or retirement of the editor specs. +- Validate the build/test graph no longer includes editor-stack-only suites. + +### Manual Verification +- Read the Studio spec README and confirm it no longer advertises the removed stack as active. +- Inspect project lessons/readme surfaces and confirm editor-stack lessons are clearly historical or retired. +- Launch the application and confirm no missing i18n keys or dead UI labels remain. + +## Acceptance Criteria + +- [ ] Studio specs no longer define the embedded editor stack as an active surface. +- [ ] Studio README/index material no longer points to removed editor/VFS/LSP architecture as current. +- [ ] Editor-specific i18n keys are removed or no longer consumed. +- [ ] Obsolete tests are removed or rewritten. +- [ ] Historical lessons are clearly demoted from active operational guidance. + +## Dependencies + +- `DEC-0031` accepted and normatively locked. +- Sufficient implementation progress that the codebase no longer depends on the removed specs/resources/tests. + +## Risks + +- Removing normative docs too early may temporarily leave the repo without clear current guidance. +- Historical lessons may still be valuable; deleting them outright could lose context that should instead be reclassified. +- Partial cleanup can leave broken links or missing i18n keys that only appear at runtime. + diff --git a/prometeu-app/src/main/java/p/studio/AppContainer.java b/prometeu-app/src/main/java/p/studio/AppContainer.java index 44e825d3..ec86a4b9 100644 --- a/prometeu-app/src/main/java/p/studio/AppContainer.java +++ b/prometeu-app/src/main/java/p/studio/AppContainer.java @@ -2,14 +2,10 @@ package p.studio; import com.fasterxml.jackson.databind.ObjectMapper; import p.packer.Packer; -import p.studio.lsp.LspServiceFactory; -import p.studio.lsp.LspServiceFactoryImpl; import p.studio.lsp.events.StudioEventBus; import p.studio.lsp.events.StudioPackerEventAdapter; import p.studio.utilities.ThemeService; import p.studio.utilities.i18n.I18nService; -import p.studio.vfs.FilesystemProjectDocumentVfsFactory; -import p.studio.vfs.ProjectDocumentVfsFactory; import java.util.concurrent.ExecutorService; import java.util.concurrent.Executors; @@ -21,8 +17,6 @@ public final class AppContainer implements Container { private final ThemeService themeService; private final StudioEventBus studioEventBus; private final ObjectMapper mapper; - private final LspServiceFactory lspServiceFactory; - private final ProjectDocumentVfsFactory projectDocumentVfsFactory; private final EmbeddedPacker embeddedPacker; private final StudioBackgroundTasks backgroundTasks; @@ -31,8 +25,6 @@ public final class AppContainer implements Container { this.themeService = new ThemeService(); this.studioEventBus = new StudioEventBus(); this.mapper = new ObjectMapper(); - this.lspServiceFactory = new LspServiceFactoryImpl(); - this.projectDocumentVfsFactory = new FilesystemProjectDocumentVfsFactory(); final ExecutorService backgroundExecutor = Executors.newFixedThreadPool(2, new StudioWorkerThreadFactory()); this.backgroundTasks = new StudioBackgroundTasks(backgroundExecutor); final Packer packer = Packer.bootstrap(this.mapper, new StudioPackerEventAdapter(studioEventBus)); @@ -59,16 +51,6 @@ public final class AppContainer implements Container { return mapper; } - @Override - public LspServiceFactory getPrometeuLspServiceFactory() { - return lspServiceFactory; - } - - @Override - public ProjectDocumentVfsFactory getProjectDocumentVfsFactory() { - return projectDocumentVfsFactory; - } - @Override public EmbeddedPacker getPacker() { return embeddedPacker; diff --git a/prometeu-studio/src/main/java/p/studio/Container.java b/prometeu-studio/src/main/java/p/studio/Container.java index a5a226da..2e9cae4e 100644 --- a/prometeu-studio/src/main/java/p/studio/Container.java +++ b/prometeu-studio/src/main/java/p/studio/Container.java @@ -1,11 +1,9 @@ package p.studio; import com.fasterxml.jackson.databind.ObjectMapper; -import p.studio.lsp.LspServiceFactory; import p.studio.lsp.events.StudioEventBus; import p.studio.utilities.ThemeService; import p.studio.utilities.i18n.I18nService; -import p.studio.vfs.ProjectDocumentVfsFactory; import java.util.Objects; import java.util.concurrent.atomic.AtomicReference; @@ -19,10 +17,6 @@ public interface Container { ObjectMapper getMapper(); - LspServiceFactory getPrometeuLspServiceFactory(); - - ProjectDocumentVfsFactory getProjectDocumentVfsFactory(); - EmbeddedPacker getPacker(); StudioBackgroundTasks getBackgroundTasks(); @@ -66,14 +60,6 @@ public interface Container { return current().getMapper(); } - static LspServiceFactory prometeuLspServiceFactory() { - return current().getPrometeuLspServiceFactory(); - } - - static ProjectDocumentVfsFactory projectDocumentVfsFactory() { - return current().getProjectDocumentVfsFactory(); - } - static EmbeddedPacker packer() { return current().getPacker(); } diff --git a/prometeu-studio/src/main/java/p/studio/projectsessions/StudioProjectSession.java b/prometeu-studio/src/main/java/p/studio/projectsessions/StudioProjectSession.java index 68401342..af36c5c7 100644 --- a/prometeu-studio/src/main/java/p/studio/projectsessions/StudioProjectSession.java +++ b/prometeu-studio/src/main/java/p/studio/projectsessions/StudioProjectSession.java @@ -1,19 +1,15 @@ package p.studio.projectsessions; import p.studio.execution.StudioExecutionSessionService; -import p.studio.lsp.LspService; import p.studio.projectstate.ProjectLocalStudioSetup; import p.studio.projectstate.ProjectLocalStudioState; import p.studio.projectstate.ProjectLocalStudioStateService; import p.studio.projects.ProjectReference; -import p.studio.vfs.VfsProjectDocument; import java.util.Objects; public final class StudioProjectSession implements AutoCloseable { private final ProjectReference projectReference; - private final LspService prometeuLspService; - private final VfsProjectDocument vfsProjectDocument; private final ProjectLocalStudioStateService projectLocalStudioStateService; private final ProjectLocalStudioSetup projectLocalStudioSetup; private final StudioExecutionSessionService executionSessionService; @@ -21,13 +17,9 @@ public final class StudioProjectSession implements AutoCloseable { private boolean closed; public StudioProjectSession( - final ProjectReference projectReference, - final LspService prometeuLspService, - final VfsProjectDocument vfsProjectDocument) { + final ProjectReference projectReference) { this( projectReference, - prometeuLspService, - vfsProjectDocument, new ProjectLocalStudioStateService(), ProjectLocalStudioSetup.defaults(), new StudioExecutionSessionService(), @@ -36,15 +28,11 @@ public final class StudioProjectSession implements AutoCloseable { StudioProjectSession( final ProjectReference projectReference, - final LspService prometeuLspService, - final VfsProjectDocument vfsProjectDocument, final ProjectLocalStudioStateService projectLocalStudioStateService, final ProjectLocalStudioSetup projectLocalStudioSetup, final StudioExecutionSessionService executionSessionService, final ProjectLocalStudioState projectLocalStudioState) { this.projectReference = Objects.requireNonNull(projectReference, "projectReference"); - this.prometeuLspService = Objects.requireNonNull(prometeuLspService, "prometeuLspService"); - this.vfsProjectDocument = Objects.requireNonNull(vfsProjectDocument, "vfsProjectDocument"); this.projectLocalStudioStateService = Objects.requireNonNull(projectLocalStudioStateService, "projectLocalStudioStateService"); this.projectLocalStudioSetup = Objects.requireNonNull(projectLocalStudioSetup, "projectLocalStudioSetup"); this.executionSessionService = Objects.requireNonNull(executionSessionService, "executionSessionService"); @@ -55,14 +43,6 @@ public final class StudioProjectSession implements AutoCloseable { return projectReference; } - public VfsProjectDocument projectDocumentVfs() { - return vfsProjectDocument; - } - - public LspService prometeuLspService() { - return prometeuLspService; - } - public ProjectLocalStudioState projectLocalStudioState() { return projectLocalStudioState; } @@ -96,25 +76,13 @@ public final class StudioProjectSession implements AutoCloseable { failure = runtimeException; } try { - prometeuLspService.close(); - } catch (RuntimeException runtimeException) { - if (failure == null) { - failure = runtimeException; - } else { - failure.addSuppressed(runtimeException); + if (failure != null) { + throw failure; } - } - try { - vfsProjectDocument.close(); - } catch (RuntimeException runtimeException) { - if (failure == null) { - failure = runtimeException; - } else { - failure.addSuppressed(runtimeException); + } finally { + if (failure != null) { + throw failure; } } - if (failure != null) { - throw failure; - } } } diff --git a/prometeu-studio/src/main/java/p/studio/projectsessions/StudioProjectSessionFactory.java b/prometeu-studio/src/main/java/p/studio/projectsessions/StudioProjectSessionFactory.java index cedb35c5..2dde9464 100644 --- a/prometeu-studio/src/main/java/p/studio/projectsessions/StudioProjectSessionFactory.java +++ b/prometeu-studio/src/main/java/p/studio/projectsessions/StudioProjectSessionFactory.java @@ -1,60 +1,36 @@ package p.studio.projectsessions; import p.studio.execution.StudioExecutionSessionService; -import p.studio.lsp.messages.LspProjectContext; -import p.studio.lsp.LspServiceFactory; import p.studio.projectstate.ProjectLocalStudioSetupService; import p.studio.projectstate.ProjectLocalStudioStateService; import p.studio.projects.ProjectReference; -import p.studio.vfs.VfsProjectDocument; -import p.studio.vfs.ProjectDocumentVfsFactory; import java.util.Objects; public final class StudioProjectSessionFactory { - private final LspServiceFactory lspServiceFactory; - private final ProjectDocumentVfsFactory projectDocumentVfsFactory; private final ProjectLocalStudioStateService projectLocalStudioStateService; private final ProjectLocalStudioSetupService projectLocalStudioSetupService; - public StudioProjectSessionFactory( - final LspServiceFactory lspServiceFactory, - final ProjectDocumentVfsFactory projectDocumentVfsFactory) { + public StudioProjectSessionFactory() { this( - lspServiceFactory, - projectDocumentVfsFactory, new ProjectLocalStudioStateService(), new ProjectLocalStudioSetupService()); } StudioProjectSessionFactory( - final LspServiceFactory lspServiceFactory, - final ProjectDocumentVfsFactory projectDocumentVfsFactory, final ProjectLocalStudioStateService projectLocalStudioStateService, final ProjectLocalStudioSetupService projectLocalStudioSetupService) { - this.lspServiceFactory = Objects.requireNonNull(lspServiceFactory, "prometeuLspServiceFactory"); - this.projectDocumentVfsFactory = Objects.requireNonNull(projectDocumentVfsFactory, "projectDocumentVfsFactory"); this.projectLocalStudioStateService = Objects.requireNonNull(projectLocalStudioStateService, "projectLocalStudioStateService"); this.projectLocalStudioSetupService = Objects.requireNonNull(projectLocalStudioSetupService, "projectLocalStudioSetupService"); } public StudioProjectSession open(final ProjectReference projectReference) { final ProjectReference target = Objects.requireNonNull(projectReference, "projectReference"); - final VfsProjectDocument vfsProjectDocument = projectDocumentVfsFactory.open(target.toVfsProjectContext()); return new StudioProjectSession( target, - lspServiceFactory.open(lspProjectContext(target), vfsProjectDocument), - vfsProjectDocument, projectLocalStudioStateService, projectLocalStudioSetupService.load(target), new StudioExecutionSessionService(), projectLocalStudioStateService.load(target)); } - - private LspProjectContext lspProjectContext(final ProjectReference projectReference) { - return new LspProjectContext( - projectReference.name(), - projectReference.languageId(), - projectReference.rootPath()); - } } diff --git a/prometeu-studio/src/main/java/p/studio/projectstate/ProjectLocalStudioState.java b/prometeu-studio/src/main/java/p/studio/projectstate/ProjectLocalStudioState.java index 7bc6278d..120b6c36 100644 --- a/prometeu-studio/src/main/java/p/studio/projectstate/ProjectLocalStudioState.java +++ b/prometeu-studio/src/main/java/p/studio/projectstate/ProjectLocalStudioState.java @@ -3,57 +3,48 @@ package p.studio.projectstate; import com.fasterxml.jackson.annotation.JsonIgnoreProperties; import java.util.ArrayList; -import java.util.LinkedHashSet; import java.util.List; @JsonIgnoreProperties(ignoreUnknown = true) public record ProjectLocalStudioState( int version, ShellLayout shellLayout, - OpenShellState openShellState, - EditorRestorationState editorRestoration) { + OpenShellState openShellState) { public static final int CURRENT_VERSION = 1; public ProjectLocalStudioState { version = version <= 0 ? CURRENT_VERSION : version; shellLayout = shellLayout == null ? ShellLayout.defaults() : shellLayout.normalize(); openShellState = openShellState == null ? OpenShellState.defaults() : openShellState.normalize(); - editorRestoration = editorRestoration == null ? EditorRestorationState.defaults() : editorRestoration.normalize(); } public static ProjectLocalStudioState defaults() { return new ProjectLocalStudioState( CURRENT_VERSION, ShellLayout.defaults(), - OpenShellState.defaults(), - EditorRestorationState.defaults()); + OpenShellState.defaults()); } public ProjectLocalStudioState withShellLayout(final ShellLayout nextShellLayout) { - return new ProjectLocalStudioState(version, nextShellLayout, openShellState, editorRestoration); + return new ProjectLocalStudioState(version, nextShellLayout, openShellState); } public ProjectLocalStudioState withOpenShellState(final OpenShellState nextOpenShellState) { - return new ProjectLocalStudioState(version, shellLayout, nextOpenShellState, editorRestoration); - } - - public ProjectLocalStudioState withEditorRestoration(final EditorRestorationState nextEditorRestoration) { - return new ProjectLocalStudioState(version, shellLayout, openShellState, nextEditorRestoration); + return new ProjectLocalStudioState(version, shellLayout, nextOpenShellState); } @JsonIgnoreProperties(ignoreUnknown = true) - public record ShellLayout(EditorLayoutState editorLayout, AssetsLayoutState assetsLayout) { + public record ShellLayout(AssetsLayoutState assetsLayout) { public ShellLayout { - editorLayout = editorLayout == null ? EditorLayoutState.defaults() : editorLayout.normalize(); assetsLayout = assetsLayout == null ? AssetsLayoutState.defaults() : assetsLayout.normalize(); } public static ShellLayout defaults() { - return new ShellLayout(EditorLayoutState.defaults(), AssetsLayoutState.defaults()); + return new ShellLayout(AssetsLayoutState.defaults()); } private ShellLayout normalize() { - return new ShellLayout(editorLayout, assetsLayout); + return new ShellLayout(assetsLayout); } } @@ -76,6 +67,9 @@ public record ProjectLocalStudioState( public record OpenShellState(String selectedWorkspaceId) { public OpenShellState { selectedWorkspaceId = normalizeText(selectedWorkspaceId); + if ("EDITOR".equals(selectedWorkspaceId)) { + selectedWorkspaceId = "ASSETS"; + } } public static OpenShellState defaults() { @@ -87,80 +81,6 @@ public record ProjectLocalStudioState( } } - @JsonIgnoreProperties(ignoreUnknown = true) - public record EditorLayoutState( - List contentSplitDividers, - List leftColumnDividers, - List rightColumnDividers, - DockPanelState outlinePanel, - DockPanelState helperPanel, - List navigatorExpandedPaths) { - public EditorLayoutState { - contentSplitDividers = normalizeDividerPositions(contentSplitDividers); - leftColumnDividers = normalizeDividerPositions(leftColumnDividers); - rightColumnDividers = normalizeDividerPositions(rightColumnDividers); - outlinePanel = outlinePanel == null ? DockPanelState.defaults() : outlinePanel.normalize(); - helperPanel = helperPanel == null ? DockPanelState.defaults() : helperPanel.normalize(); - navigatorExpandedPaths = normalizePaths(navigatorExpandedPaths); - } - - public static EditorLayoutState defaults() { - return new EditorLayoutState( - List.of(), - List.of(), - List.of(), - DockPanelState.defaults(), - DockPanelState.defaults(), - List.of()); - } - - private EditorLayoutState normalize() { - return new EditorLayoutState( - contentSplitDividers, - leftColumnDividers, - rightColumnDividers, - outlinePanel, - helperPanel, - navigatorExpandedPaths); - } - } - - @JsonIgnoreProperties(ignoreUnknown = true) - public record DockPanelState(boolean expanded, Double dividerPosition) { - public DockPanelState { - dividerPosition = normalizeDividerPosition(dividerPosition); - } - - public static DockPanelState defaults() { - return new DockPanelState(true, null); - } - - private DockPanelState normalize() { - return new DockPanelState(expanded, dividerPosition); - } - } - - @JsonIgnoreProperties(ignoreUnknown = true) - public record EditorRestorationState(List openTabPaths, String activeTabPath) { - public EditorRestorationState { - openTabPaths = normalizePaths(openTabPaths); - activeTabPath = normalizeText(activeTabPath); - if (activeTabPath != null && !openTabPaths.contains(activeTabPath)) { - final List expanded = new ArrayList<>(openTabPaths); - expanded.add(activeTabPath); - openTabPaths = List.copyOf(expanded); - } - } - - public static EditorRestorationState defaults() { - return new EditorRestorationState(List.of(), null); - } - - private EditorRestorationState normalize() { - return new EditorRestorationState(openTabPaths, activeTabPath); - } - } - private static String normalizeText(final String value) { if (value == null) { return null; @@ -169,20 +89,6 @@ public record ProjectLocalStudioState( return trimmed.isEmpty() ? null : trimmed; } - private static List normalizePaths(final List values) { - if (values == null || values.isEmpty()) { - return List.of(); - } - final LinkedHashSet normalized = new LinkedHashSet<>(); - for (final String value : values) { - final String text = normalizeText(value); - if (text != null) { - normalized.add(text); - } - } - return List.copyOf(normalized); - } - private static List normalizeDividerPositions(final List values) { if (values == null || values.isEmpty()) { return List.of(); @@ -196,11 +102,4 @@ public record ProjectLocalStudioState( } return List.copyOf(normalized); } - - private static Double normalizeDividerPosition(final Double value) { - if (value == null || value.isNaN() || value.isInfinite()) { - return null; - } - return Math.max(0.0d, Math.min(1.0d, value)); - } } diff --git a/prometeu-studio/src/main/java/p/studio/window/MainView.java b/prometeu-studio/src/main/java/p/studio/window/MainView.java index 5a1a89d8..3fa406e6 100644 --- a/prometeu-studio/src/main/java/p/studio/window/MainView.java +++ b/prometeu-studio/src/main/java/p/studio/window/MainView.java @@ -15,7 +15,6 @@ import p.studio.workspaces.WorkspaceId; import p.studio.workspaces.assets.AssetWorkspace; import p.studio.workspaces.builder.ShipperWorkspace; import p.studio.workspaces.debug.DebugWorkspace; -import p.studio.workspaces.editor.EditorWorkspace; import java.util.List; @@ -24,7 +23,6 @@ public final class MainView extends BorderPane { private final ProjectReference projectReference; private final StudioProjectSession projectSession; private final AssetWorkspace assetWorkspace; - private final EditorWorkspace editorWorkspace; private final StudioWorkspaceRailControl workspaceRail; private final StudioPlayStopCoordinator playStopCoordinator; private boolean initializing; @@ -50,23 +48,14 @@ public final class MainView extends BorderPane { assetWorkspace = new AssetWorkspace(projectReference); host.register(assetWorkspace); - editorWorkspace = new EditorWorkspace( - projectReference, - projectSession.projectDocumentVfs(), - projectSession.prometeuLspService(), - projectSetup.editorIndentation()); - host.register(editorWorkspace); assetWorkspace.restoreProjectLocalState(persistedState); - editorWorkspace.restoreProjectLocalState(persistedState); assetWorkspace.setStateChangedAction(this::persistProjectLocalState); - editorWorkspace.setStateChangedAction(this::persistProjectLocalState); host.register(new DebugWorkspace(projectReference, projectSession.executionSession())); host.register(new ShipperWorkspace(projectReference)); workspaceRail = new StudioWorkspaceRailControl<>( List.of( new StudioWorkspaceRailItem<>(WorkspaceId.ASSETS, "📦", Container.i18n().bind(I18n.WORKSPACE_ASSETS)), - new StudioWorkspaceRailItem<>(WorkspaceId.EDITOR, "📝", Container.i18n().bind(I18n.WORKSPACE_CODE)), new StudioWorkspaceRailItem<>(WorkspaceId.DEBUG, "🎮", Container.i18n().bind(I18n.WORKSPACE_DEBUG)), new StudioWorkspaceRailItem<>(WorkspaceId.SHIPPER, "⚙️", Container.i18n().bind(I18n.WORKSPACE_SHIPPER)) ), @@ -102,14 +91,11 @@ public final class MainView extends BorderPane { projectSession.replaceProjectLocalStudioState( current.withOpenShellState(new ProjectLocalStudioState.OpenShellState(selectedWorkspace.name())) .withShellLayout(new ProjectLocalStudioState.ShellLayout( - editorWorkspace.captureLayoutState(), - assetWorkspace.captureLayoutState())) - .withEditorRestoration(editorWorkspace.captureRestorationState())); + assetWorkspace.captureLayoutState()))); } public void reapplyProjectLocalLayout() { assetWorkspace.reapplyPendingLayoutState(); - editorWorkspace.reapplyPendingLayoutState(); } public void close() { diff --git a/prometeu-studio/src/main/java/p/studio/window/StudioWindowCoordinator.java b/prometeu-studio/src/main/java/p/studio/window/StudioWindowCoordinator.java index e198201b..b0be78b2 100644 --- a/prometeu-studio/src/main/java/p/studio/window/StudioWindowCoordinator.java +++ b/prometeu-studio/src/main/java/p/studio/window/StudioWindowCoordinator.java @@ -37,9 +37,7 @@ public final class StudioWindowCoordinator { this.projectCatalogService = new ProjectCatalogService(resolveDefaultProjectsRoot()); this.knownProjectsService = new KnownProjectsService(resolveKnownProjectsStorage(), projectCatalogService); this.windowStateService = new WindowStateService(resolveWindowStateStorage()); - this.projectSessionFactory = new StudioProjectSessionFactory( - Container.prometeuLspServiceFactory(), - Container.projectDocumentVfsFactory()); + this.projectSessionFactory = new StudioProjectSessionFactory(); this.launcherView = new ProjectLauncherView( knownProjectsService, projectCatalogService, diff --git a/prometeu-studio/src/main/java/p/studio/workspaces/WorkspaceId.java b/prometeu-studio/src/main/java/p/studio/workspaces/WorkspaceId.java index 8f0b043e..c3c88b44 100644 --- a/prometeu-studio/src/main/java/p/studio/workspaces/WorkspaceId.java +++ b/prometeu-studio/src/main/java/p/studio/workspaces/WorkspaceId.java @@ -1,7 +1,6 @@ package p.studio.workspaces; public enum WorkspaceId { - EDITOR, ASSETS, SHIPPER, DEBUG diff --git a/prometeu-studio/src/main/java/p/studio/workspaces/editor/EditorDocumentHighlightOwner.java b/prometeu-studio/src/main/java/p/studio/workspaces/editor/EditorDocumentHighlightOwner.java deleted file mode 100644 index 9e24dded..00000000 --- a/prometeu-studio/src/main/java/p/studio/workspaces/editor/EditorDocumentHighlightOwner.java +++ /dev/null @@ -1,6 +0,0 @@ -package p.studio.workspaces.editor; - -enum EditorDocumentHighlightOwner { - LOCAL, - LSP -} diff --git a/prometeu-studio/src/main/java/p/studio/workspaces/editor/EditorDocumentHighlightingResult.java b/prometeu-studio/src/main/java/p/studio/workspaces/editor/EditorDocumentHighlightingResult.java deleted file mode 100644 index 6323aacf..00000000 --- a/prometeu-studio/src/main/java/p/studio/workspaces/editor/EditorDocumentHighlightingResult.java +++ /dev/null @@ -1,20 +0,0 @@ -package p.studio.workspaces.editor; - -import org.fxmisc.richtext.model.StyleSpans; -import p.studio.lsp.dtos.LspInlineHintDTO; - -import java.util.Collection; -import java.util.List; -import java.util.Objects; - -record EditorDocumentHighlightingResult( - EditorDocumentHighlightOwner owner, - StyleSpans> styleSpans, - List inlineHints) { - - EditorDocumentHighlightingResult { - owner = Objects.requireNonNull(owner, "owner"); - styleSpans = Objects.requireNonNull(styleSpans, "styleSpans"); - inlineHints = List.copyOf(Objects.requireNonNull(inlineHints, "inlineHints")); - } -} diff --git a/prometeu-studio/src/main/java/p/studio/workspaces/editor/EditorDocumentHighlightingRouter.java b/prometeu-studio/src/main/java/p/studio/workspaces/editor/EditorDocumentHighlightingRouter.java deleted file mode 100644 index c5cf550a..00000000 --- a/prometeu-studio/src/main/java/p/studio/workspaces/editor/EditorDocumentHighlightingRouter.java +++ /dev/null @@ -1,32 +0,0 @@ -package p.studio.workspaces.editor; - -import p.studio.lsp.messages.LspAnalyzeDocumentResult; -import p.studio.workspaces.editor.syntaxhighlight.EditorDocumentSemanticHighlighting; - -final class EditorDocumentHighlightingRouter { - private EditorDocumentHighlightingRouter() { - } - - static EditorDocumentHighlightingResult route( - final EditorOpenFileBuffer fileBuffer, - final EditorDocumentPresentation presentation, - final LspAnalyzeDocumentResult analysis) { - final var localHighlighting = presentation.highlight(fileBuffer.content()); - final var inlineHints = EditorDocumentInlineHintRouter.route(fileBuffer, analysis); - if (fileBuffer.frontendDocument() - && analysis != null - && presentation.supportsSemanticHighlighting() - && !analysis.semanticHighlights().isEmpty()) { - return new EditorDocumentHighlightingResult( - EditorDocumentHighlightOwner.LSP, - EditorDocumentSemanticHighlighting.overlay( - localHighlighting, - EditorDocumentSemanticHighlighting.highlight(fileBuffer.content(), analysis.semanticHighlights())), - inlineHints); - } - return new EditorDocumentHighlightingResult( - EditorDocumentHighlightOwner.LOCAL, - localHighlighting, - inlineHints); - } -} diff --git a/prometeu-studio/src/main/java/p/studio/workspaces/editor/EditorDocumentInlineHintRouter.java b/prometeu-studio/src/main/java/p/studio/workspaces/editor/EditorDocumentInlineHintRouter.java deleted file mode 100644 index 84065142..00000000 --- a/prometeu-studio/src/main/java/p/studio/workspaces/editor/EditorDocumentInlineHintRouter.java +++ /dev/null @@ -1,20 +0,0 @@ -package p.studio.workspaces.editor; - -import p.studio.lsp.dtos.LspInlineHintDTO; -import p.studio.lsp.messages.LspAnalyzeDocumentResult; - -import java.util.List; - -final class EditorDocumentInlineHintRouter { - private EditorDocumentInlineHintRouter() { - } - - static List route( - final EditorOpenFileBuffer fileBuffer, - final LspAnalyzeDocumentResult analysis) { - if (!fileBuffer.frontendDocument() || analysis == null || analysis.inlineHints().isEmpty()) { - return List.of(); - } - return analysis.inlineHints(); - } -} diff --git a/prometeu-studio/src/main/java/p/studio/workspaces/editor/EditorDocumentPresentation.java b/prometeu-studio/src/main/java/p/studio/workspaces/editor/EditorDocumentPresentation.java deleted file mode 100644 index 2b7dd55f..00000000 --- a/prometeu-studio/src/main/java/p/studio/workspaces/editor/EditorDocumentPresentation.java +++ /dev/null @@ -1,30 +0,0 @@ -package p.studio.workspaces.editor; - -import org.fxmisc.richtext.model.StyleSpans; -import p.studio.workspaces.editor.syntaxhighlight.EditorDocumentSyntaxHighlighting; - -import java.util.Collection; -import java.util.List; -import java.util.Objects; - -record EditorDocumentPresentation( - String styleKey, - List stylesheetUrls, - List semanticKeys, - EditorDocumentSyntaxHighlighting syntaxHighlighting) { - - EditorDocumentPresentation { - styleKey = Objects.requireNonNull(styleKey, "styleKey"); - stylesheetUrls = List.copyOf(Objects.requireNonNull(stylesheetUrls, "stylesheetUrls")); - semanticKeys = List.copyOf(Objects.requireNonNull(semanticKeys, "semanticKeys")); - syntaxHighlighting = Objects.requireNonNull(syntaxHighlighting, "syntaxHighlighting"); - } - - StyleSpans> highlight(final String content) { - return syntaxHighlighting.highlight(content); - } - - boolean supportsSemanticHighlighting() { - return !semanticKeys.isEmpty() && !stylesheetUrls.isEmpty(); - } -} diff --git a/prometeu-studio/src/main/java/p/studio/workspaces/editor/EditorDocumentPresentationRegistry.java b/prometeu-studio/src/main/java/p/studio/workspaces/editor/EditorDocumentPresentationRegistry.java deleted file mode 100644 index 846b280c..00000000 --- a/prometeu-studio/src/main/java/p/studio/workspaces/editor/EditorDocumentPresentationRegistry.java +++ /dev/null @@ -1,122 +0,0 @@ -package p.studio.workspaces.editor; - -import p.studio.compiler.FrontendRegistryService; -import p.studio.compiler.models.FrontendSemanticPresentationSpec; -import p.studio.lsp.dtos.LspSemanticPresentationDTO; -import p.studio.vfs.messages.VfsDocumentTypeIds; -import p.studio.workspaces.editor.syntaxhighlight.EditorDocumentSyntaxHighlighting; - -import java.net.URL; -import java.util.Locale; -import java.util.Objects; -import java.util.Optional; -import java.util.logging.Logger; - -final class EditorDocumentPresentationRegistry { - private static final Logger LOGGER = Logger.getLogger(EditorDocumentPresentationRegistry.class.getName()); - private static final EditorDocumentPresentation TEXT_PRESENTATION = new EditorDocumentPresentation( - "text", - java.util.List.of(), - java.util.List.of(), - EditorDocumentSyntaxHighlighting.plainText()); - private static final EditorDocumentPresentation JSON_PRESENTATION = new EditorDocumentPresentation( - "json", - java.util.List.of(stylesheet("presentations/json.css")), - java.util.List.of(), - EditorDocumentSyntaxHighlighting.json()); - private static final EditorDocumentPresentation BASH_PRESENTATION = new EditorDocumentPresentation( - "bash", - java.util.List.of(stylesheet("presentations/bash.css")), - java.util.List.of(), - EditorDocumentSyntaxHighlighting.bash()); - - EditorDocumentPresentation resolve(final String typeId) { - return resolve(typeId, null); - } - - EditorDocumentPresentation resolve( - final String typeId, - final LspSemanticPresentationDTO semanticPresentation) { - final String normalizedTypeId = normalize(typeId); - if (normalizedTypeId.isBlank()) { - return TEXT_PRESENTATION; - } - if (FrontendRegistryService.getFrontendSpec(normalizedTypeId).isPresent()) { - return frontendPresentation(normalizedTypeId, semanticPresentation); - } - if (VfsDocumentTypeIds.JSON.equals(normalizedTypeId)) { - return JSON_PRESENTATION; - } - if (VfsDocumentTypeIds.BASH.equals(normalizedTypeId)) { - return BASH_PRESENTATION; - } - return TEXT_PRESENTATION; - } - - private EditorDocumentPresentation frontendPresentation( - final String normalizedTypeId, - final LspSemanticPresentationDTO semanticPresentation) { - final var frontendSpec = FrontendRegistryService.getFrontendSpec(normalizedTypeId).orElseThrow(); - final FrontendSemanticPresentationSpec frontendPresentationSpec = frontendSpec.getSemanticPresentation(); - final java.util.List stylesheetUrls = resolveFrontendStylesheets( - semanticPresentation == null ? java.util.List.of() : semanticPresentation.resources(), - frontendPresentationSpec.resources()); - final java.util.List semanticKeys = semanticPresentation == null - ? frontendPresentationSpec.semanticKeys() - : semanticPresentation.semanticKeys(); - return new EditorDocumentPresentation( - normalizedTypeId, - stylesheetUrls, - semanticKeys, - frontendSyntaxHighlighting(normalizedTypeId)); - } - - private String normalize(final String typeId) { - return typeId == null ? "" : typeId.trim().toLowerCase(Locale.ROOT); - } - - private static String stylesheet(final String relativePath) { - return java.util.Objects.requireNonNull( - EditorDocumentPresentationRegistry.class.getResource("/themes/editor/" + relativePath), - "missing editor presentation stylesheet: " + relativePath) - .toExternalForm(); - } - - private static Optional resourceStylesheet(final String resourcePath) { - final String normalizedPath = normalizeResourcePath(resourcePath); - final URL resource = EditorDocumentPresentationRegistry.class.getResource(normalizedPath); - if (resource == null) { - LOGGER.fine("missing frontend semantic presentation resource: " + resourcePath); - return Optional.empty(); - } - return Optional.of(resource.toExternalForm()); - } - - private static java.util.List resolveFrontendStylesheets( - final java.util.List primaryResources, - final java.util.List fallbackResources) { - final java.util.List primary = primaryResources.stream() - .map(EditorDocumentPresentationRegistry::resourceStylesheet) - .flatMap(Optional::stream) - .toList(); - if (!primary.isEmpty()) { - return primary; - } - return fallbackResources.stream() - .map(EditorDocumentPresentationRegistry::resourceStylesheet) - .flatMap(Optional::stream) - .toList(); - } - - private static EditorDocumentSyntaxHighlighting frontendSyntaxHighlighting(final String normalizedTypeId) { - return EditorDocumentSyntaxHighlighting.plainText(); - } - - private static String normalizeResourcePath(final String resourcePath) { - final String normalized = Objects.requireNonNull(resourcePath, "resourcePath").trim(); - if (normalized.isEmpty()) { - throw new IllegalArgumentException("resourcePath cannot be blank"); - } - return normalized.startsWith("/") ? normalized : "/" + normalized; - } -} diff --git a/prometeu-studio/src/main/java/p/studio/workspaces/editor/EditorDocumentPresentationStyles.java b/prometeu-studio/src/main/java/p/studio/workspaces/editor/EditorDocumentPresentationStyles.java deleted file mode 100644 index cf0bedcb..00000000 --- a/prometeu-studio/src/main/java/p/studio/workspaces/editor/EditorDocumentPresentationStyles.java +++ /dev/null @@ -1,28 +0,0 @@ -package p.studio.workspaces.editor; - -import javafx.scene.Node; -import javafx.scene.control.Label; - -final class EditorDocumentPresentationStyles { - private static final String CODE_AREA_TYPE_CLASS_PREFIX = "editor-workspace-code-area-type-"; - private static final String STATUS_CHIP_TYPE_CLASS_PREFIX = "editor-workspace-status-chip-type-"; - - private EditorDocumentPresentationStyles() { - } - - static void applyToCodeArea(final Node node, final EditorDocumentPresentation presentation) { - replaceTypeClass(node, CODE_AREA_TYPE_CLASS_PREFIX, presentation.styleKey()); - } - - static void applyToStatusChip(final Label label, final EditorDocumentPresentation presentation) { - replaceTypeClass(label, STATUS_CHIP_TYPE_CLASS_PREFIX, presentation.styleKey()); - } - - private static void replaceTypeClass( - final Node node, - final String prefix, - final String styleKey) { - node.getStyleClass().removeIf(styleClass -> styleClass.startsWith(prefix)); - node.getStyleClass().add(prefix + styleKey); - } -} diff --git a/prometeu-studio/src/main/java/p/studio/workspaces/editor/EditorDocumentScopeGuideGraphicFactory.java b/prometeu-studio/src/main/java/p/studio/workspaces/editor/EditorDocumentScopeGuideGraphicFactory.java deleted file mode 100644 index d079e7fc..00000000 --- a/prometeu-studio/src/main/java/p/studio/workspaces/editor/EditorDocumentScopeGuideGraphicFactory.java +++ /dev/null @@ -1,91 +0,0 @@ -package p.studio.workspaces.editor; - -import javafx.scene.Node; -import javafx.scene.canvas.Canvas; -import javafx.scene.canvas.GraphicsContext; -import javafx.scene.layout.HBox; -import javafx.scene.layout.Region; -import javafx.scene.paint.Color; - -final class EditorDocumentScopeGuideGraphicFactory { - private static final double COLUMN_WIDTH = 10.0; - private static final double CANVAS_PADDING = 6.0; - private static final double CONTAINER_X = CANVAS_PADDING + (COLUMN_WIDTH / 2.0); - private static final double SCOPE_X = CANVAS_PADDING + COLUMN_WIDTH + (COLUMN_WIDTH / 2.0); - private static final double GUIDE_CAP = 4.0; - private static final Color CONTAINER_COLOR = Color.web("#5f7896"); - private static final Color SCOPE_COLOR = Color.web("#8f72ff"); - - private EditorDocumentScopeGuideGraphicFactory() { - } - - static Node create( - final Node lineNumberNode, - final int paragraphIndex, - final EditorDocumentScopeGuideModel model, - final EditorDocumentScopeGuideModel.ActiveGuides activeGuides) { - final var container = new HBox(lineNumberNode); - final var segments = model.segmentsForLine(paragraphIndex, activeGuides); - container.getChildren().add(new ScopeGuideCanvas(segments)); - return container; - } - - private static final class ScopeGuideCanvas extends Region { - private final Canvas canvas = new Canvas(); - private final java.util.List segments; - - private ScopeGuideCanvas( - final java.util.List segments) { - this.segments = segments; - getStyleClass().add("editor-workspace-scope-guide-gutter"); - getChildren().add(canvas); - setMinWidth(computeGuideWidth()); - setPrefWidth(computeGuideWidth()); - setMaxWidth(computeGuideWidth()); - } - - @Override - protected double computePrefWidth(final double height) { - return computeGuideWidth(); - } - - @Override - protected void layoutChildren() { - final double width = snapSizeX(getWidth()); - final double height = Math.max(1.0, snapSizeY(getHeight())); - canvas.setWidth(width); - canvas.setHeight(height); - draw(width, height); - } - - private void draw(final double width, final double height) { - final GraphicsContext graphics = canvas.getGraphicsContext2D(); - graphics.clearRect(0, 0, width, height); - if (segments.isEmpty()) { - return; - } - final double centerY = Math.floor(height / 2.0); - for (final var segment : segments) { - final boolean container = segment.role() == EditorDocumentScopeGuideModel.GuideRole.ACTIVE_CONTAINER; - final double x = container ? CONTAINER_X : SCOPE_X; - graphics.setLineWidth(container ? 1.0 : 1.4); - graphics.setStroke(container ? CONTAINER_COLOR : SCOPE_COLOR); - switch (segment.kind()) { - case START -> { - graphics.strokeLine(x, centerY, x, height); - graphics.strokeLine(x, centerY, x + GUIDE_CAP, centerY); - } - case CONTINUE -> graphics.strokeLine(x, 0, x, height); - case END -> { - graphics.strokeLine(x, 0, x, centerY); - graphics.strokeLine(x, centerY, x + GUIDE_CAP, centerY); - } - } - } - } - - private static double computeGuideWidth() { - return CANVAS_PADDING * 2.0 + (COLUMN_WIDTH * 2.0); - } - } -} diff --git a/prometeu-studio/src/main/java/p/studio/workspaces/editor/EditorDocumentScopeGuideModel.java b/prometeu-studio/src/main/java/p/studio/workspaces/editor/EditorDocumentScopeGuideModel.java deleted file mode 100644 index b38a6706..00000000 --- a/prometeu-studio/src/main/java/p/studio/workspaces/editor/EditorDocumentScopeGuideModel.java +++ /dev/null @@ -1,340 +0,0 @@ -package p.studio.workspaces.editor; - -import p.studio.lsp.dtos.LspRangeDTO; -import p.studio.lsp.dtos.LspStructuralAnchorDTO; -import p.studio.lsp.dtos.LspSymbolDTO; -import p.studio.lsp.messages.LspSymbolKind; - -import java.util.ArrayList; -import java.util.Collections; -import java.util.Comparator; -import java.util.List; -import java.util.Objects; - -final class EditorDocumentScopeGuideModel { - private static final EditorDocumentScopeGuideModel EMPTY = - new EditorDocumentScopeGuideModel(List.of(), List.of(0), 0); - - private final List ranges; - private final List lineStarts; - private final int contentLength; - - private EditorDocumentScopeGuideModel( - final List ranges, - final List lineStarts, - final int contentLength) { - this.ranges = ranges; - this.lineStarts = lineStarts; - this.contentLength = contentLength; - } - - static EditorDocumentScopeGuideModel empty() { - return EMPTY; - } - - static EditorDocumentScopeGuideModel from( - final String content, - final List symbols) { - return fromRanges( - content, - symbols, - 0, - null, - (symbol, depth, parentId, nextId, lineStarts, contentLength) -> { - if (symbol.kind() == LspSymbolKind.UNKNOWN) { - return null; - } - final LspRangeDTO range = symbol.range(); - return toGuideRange( - lineStarts, - contentLength, - range, - new LspRangeDTO(range.startOffset(), Math.min(range.endOffset(), range.startOffset() + 1)), - new LspRangeDTO(Math.max(range.startOffset(), range.endOffset() - 1), range.endOffset()), - depth, - parentId, - nextId[0]); - }, - LspSymbolDTO::children); - } - - static EditorDocumentScopeGuideModel fromStructuralAnchors( - final String content, - final List structuralAnchors) { - return fromRanges( - content, - structuralAnchors, - 0, - null, - (anchor, depth, parentId, nextId, lineStarts, contentLength) -> toGuideRange( - lineStarts, - contentLength, - anchor.range(), - anchor.startAnchor(), - anchor.endAnchor(), - depth, - parentId, - nextId[0]), - LspStructuralAnchorDTO::children); - } - - private static EditorDocumentScopeGuideModel fromRanges( - final String content, - final List roots, - final int initialDepth, - final Integer initialParentId, - final RangeFactory rangeFactory, - final ChildAccessor childAccessor) { - final List lineStarts = lineStarts(content); - final List ranges = new ArrayList<>(); - final int[] nextId = new int[] {1}; - for (final T root : roots) { - appendRangeNode( - ranges, - lineStarts, - content.length(), - root, - initialDepth, - initialParentId, - nextId, - rangeFactory, - childAccessor); - } - ranges.sort(Comparator - .comparingInt(GuideRange::startOffset) - .thenComparingInt(GuideRange::depth) - .thenComparingInt(GuideRange::endOffset)); - return new EditorDocumentScopeGuideModel(List.copyOf(ranges), lineStarts, content.length()); - } - - ActiveGuides resolveActiveGuides(final int caretOffset) { - if (ranges.isEmpty()) { - return ActiveGuides.empty(); - } - final int probeOffset = clampCaretOffset(caretOffset); - GuideRange activeScope = null; - for (final GuideRange range : ranges) { - if (!contains(range, probeOffset)) { - continue; - } - if (activeScope == null - || span(range) < span(activeScope) - || (span(range) == span(activeScope) && range.depth() > activeScope.depth())) { - activeScope = range; - } - } - if (activeScope == null) { - return ActiveGuides.empty(); - } - final GuideRange activeContainer = activeScope.parentId() == null - ? null - : findById(activeScope.parentId()); - return new ActiveGuides(activeContainer, activeScope); - } - - List segmentsForLine( - final int lineIndex, - final ActiveGuides activeGuides) { - if (lineIndex < 0 || lineIndex >= totalLines() || activeGuides.isEmpty()) { - return List.of(); - } - final List segments = new ArrayList<>(2); - appendSegments(segments, lineIndex, activeGuides.activeContainer(), GuideRole.ACTIVE_CONTAINER); - appendSegments(segments, lineIndex, activeGuides.activeScope(), GuideRole.ACTIVE_SCOPE); - return List.copyOf(segments); - } - - int totalLines() { - return lineStarts.size(); - } - - private static void appendRangeNode( - final List ranges, - final List lineStarts, - final int contentLength, - final T node, - final int depth, - final Integer parentId, - final int[] nextId, - final RangeFactory rangeFactory, - final ChildAccessor childAccessor) { - Integer currentParentId = parentId; - final GuideRange range = rangeFactory.create(node, depth, parentId, nextId, lineStarts, contentLength); - if (range != null) { - ranges.add(range); - currentParentId = range.id(); - nextId[0]++; - } - for (final T child : childAccessor.children(node)) { - appendRangeNode(ranges, lineStarts, contentLength, child, depth + 1, currentParentId, nextId, rangeFactory, childAccessor); - } - } - - private static GuideRange toGuideRange( - final List lineStarts, - final int contentLength, - final LspRangeDTO range, - final LspRangeDTO startAnchor, - final LspRangeDTO endAnchor, - final int depth, - final Integer parentId, - final int id) { - final int startOffset = clamp(range.startOffset(), 0, contentLength); - final int endOffset = Math.max(startOffset, clamp(range.endOffset(), 0, contentLength)); - final int startAnchorOffset = clamp(startAnchor.startOffset(), startOffset, endOffset); - final int endAnchorOffset = clamp(Math.max(startAnchorOffset, endAnchor.startOffset()), startOffset, endOffset); - final int startLine = lineForOffset(lineStarts, startAnchorOffset); - final int inclusiveEndOffset = Math.max(startOffset, Math.max(startOffset, endOffset) - 1); - final int inclusiveEndAnchorOffset = Math.max( - startAnchorOffset, - Math.min(Math.max(startOffset, endOffset) - 1, Math.max(endAnchorOffset, startAnchorOffset))); - final int endLine = lineForOffset(lineStarts, clamp(inclusiveEndAnchorOffset, 0, contentLength)); - if (endLine <= startLine) { - return null; - } - return new GuideRange(id, depth, startOffset, endOffset, startAnchorOffset, endAnchorOffset, startLine, endLine, parentId); - } - - private GuideRange findById(final int id) { - for (final GuideRange range : ranges) { - if (range.id() == id) { - return range; - } - } - return null; - } - - private int clampCaretOffset(final int offset) { - if (contentLength <= 0) { - return 0; - } - return clamp(offset, 0, contentLength - 1); - } - - private static boolean contains(final GuideRange range, final int offset) { - return offset >= range.startOffset() && offset < range.endOffset(); - } - - private static int span(final GuideRange range) { - return range.endOffset() - range.startOffset(); - } - - private static void appendSegments( - final List segments, - final int lineIndex, - final GuideRange range, - final GuideRole role) { - if (range == null || lineIndex < range.startLine() || lineIndex > range.endLine()) { - return; - } - final GuideSegmentKind kind; - if (lineIndex == range.startLine()) { - kind = GuideSegmentKind.START; - } else if (lineIndex == range.endLine()) { - kind = GuideSegmentKind.END; - } else { - kind = GuideSegmentKind.CONTINUE; - } - segments.add(new ActiveGuideSegment(role, kind)); - } - - private static List lineStarts(final String content) { - if (content.isEmpty()) { - return List.of(0); - } - final List starts = new ArrayList<>(); - starts.add(0); - for (int index = 0; index < content.length(); index++) { - if (content.charAt(index) == '\n') { - starts.add(index + 1); - } - } - return Collections.unmodifiableList(starts); - } - - private static int lineForOffset(final List lineStarts, final int offset) { - int low = 0; - int high = lineStarts.size() - 1; - while (low <= high) { - final int mid = (low + high) >>> 1; - final int start = lineStarts.get(mid); - final int nextStart = mid + 1 < lineStarts.size() ? lineStarts.get(mid + 1) : Integer.MAX_VALUE; - if (offset < start) { - high = mid - 1; - continue; - } - if (offset >= nextStart) { - low = mid + 1; - continue; - } - return mid; - } - return Math.max(0, Math.min(lineStarts.size() - 1, low)); - } - - private static int clamp(final int value, final int minimum, final int maximum) { - return Math.max(minimum, Math.min(maximum, value)); - } - - enum GuideRole { - ACTIVE_CONTAINER, - ACTIVE_SCOPE - } - - enum GuideSegmentKind { - START, - CONTINUE, - END - } - - record GuideRange( - int id, - int depth, - int startOffset, - int endOffset, - int startAnchorOffset, - int endAnchorOffset, - int startLine, - int endLine, - Integer parentId) { - } - - record ActiveGuides( - GuideRange activeContainer, - GuideRange activeScope) { - private static final ActiveGuides EMPTY = new ActiveGuides(null, null); - - static ActiveGuides empty() { - return EMPTY; - } - - boolean isEmpty() { - return activeScope == null; - } - } - - record ActiveGuideSegment( - GuideRole role, - GuideSegmentKind kind) { - ActiveGuideSegment { - Objects.requireNonNull(role, "role"); - Objects.requireNonNull(kind, "kind"); - } - } - - @FunctionalInterface - private interface ChildAccessor { - List children(T node); - } - - @FunctionalInterface - private interface RangeFactory { - GuideRange create( - T node, - int depth, - Integer parentId, - int[] nextId, - List lineStarts, - int contentLength); - } -} diff --git a/prometeu-studio/src/main/java/p/studio/workspaces/editor/EditorHelperPanel.java b/prometeu-studio/src/main/java/p/studio/workspaces/editor/EditorHelperPanel.java deleted file mode 100644 index ba8ef5ef..00000000 --- a/prometeu-studio/src/main/java/p/studio/workspaces/editor/EditorHelperPanel.java +++ /dev/null @@ -1,96 +0,0 @@ -package p.studio.workspaces.editor; - -import javafx.geometry.Insets; -import javafx.scene.control.Label; -import javafx.scene.control.ScrollPane; -import javafx.scene.layout.VBox; -import p.studio.Container; -import p.studio.controls.WorkspaceDockPane; -import p.studio.lsp.dtos.LspDiagnosticDTO; -import p.studio.utilities.i18n.I18n; - -import java.nio.file.Path; -import java.util.List; - -public final class EditorHelperPanel extends WorkspaceDockPane { - public static final double COLLAPSED_HEIGHT = 34.0; - public static final double MINIMUM_EXPANDED_HEIGHT = 120.0; - public static final double DEFAULT_EXPANDED_HEIGHT = 180.0; - private final Label summary = new Label(); - private final Label diagnosticsTitle = new Label(); - private final VBox diagnosticsBox = new VBox(6); - - public EditorHelperPanel() { - super( - Container.i18n().bind(I18n.CODE_EDITOR_HELPER_TITLE), - COLLAPSED_HEIGHT, - MINIMUM_EXPANDED_HEIGHT, - DEFAULT_EXPANDED_HEIGHT, - false, - "editor-workspace-helper-pane", - "editor-workspace-helper-panel"); - - summary.getStyleClass().addAll("editor-workspace-placeholder", "editor-workspace-helper-summary"); - summary.setWrapText(true); - diagnosticsTitle.textProperty().bind(Container.i18n().bind(I18n.CODE_EDITOR_HELPER_DIAGNOSTICS)); - diagnosticsTitle.getStyleClass().add("editor-workspace-outline-section-title"); - diagnosticsBox.getStyleClass().add("editor-workspace-outline-list"); - - final var content = new VBox(10, summary, diagnosticsTitle, diagnosticsBox); - content.getStyleClass().add("editor-workspace-panel-content"); - content.setPadding(new Insets(10, 16, 14, 16)); - final var scrollPane = new ScrollPane(content); - scrollPane.setFitToWidth(true); - scrollPane.getStyleClass().add("editor-workspace-outline-scroll"); - setDockContent(scrollPane); - showPlaceholder(); - } - - public void showPlaceholder() { - summary.textProperty().unbind(); - summary.textProperty().bind(Container.i18n().bind(I18n.CODE_EDITOR_HELPER_PLACEHOLDER)); - diagnosticsBox.getChildren().setAll(placeholderLabel(I18n.CODE_EDITOR_HELPER_EMPTY_DIAGNOSTICS)); - } - - public void showSemanticReadResult( - final Path documentPath, - final List diagnostics) { - summary.textProperty().unbind(); - summary.setText(documentPath.getFileName() + " • semantic read-only"); - rebuildDiagnostics(diagnostics); - } - - private void rebuildDiagnostics(final List diagnostics) { - diagnosticsBox.getChildren().clear(); - if (diagnostics.isEmpty()) { - diagnosticsBox.getChildren().add(placeholderLabel(I18n.CODE_EDITOR_HELPER_EMPTY_DIAGNOSTICS)); - return; - } - for (final LspDiagnosticDTO diagnostic : diagnostics) { - final var label = new Label(formatDiagnostic(diagnostic)); - label.setWrapText(true); - label.getStyleClass().addAll( - "editor-workspace-outline-item", - diagnostic.severity().name().equals("ERROR") - ? "editor-workspace-outline-diagnostic-error" - : "editor-workspace-outline-diagnostic-warning"); - diagnosticsBox.getChildren().add(label); - } - } - - private Label placeholderLabel(final I18n key) { - final var label = new Label(); - label.textProperty().bind(Container.i18n().bind(key)); - label.setWrapText(true); - label.getStyleClass().addAll("editor-workspace-placeholder", "editor-workspace-outline-item"); - return label; - } - - private String formatDiagnostic(final LspDiagnosticDTO diagnostic) { - return "%s [%d,%d) %s".formatted( - diagnostic.severity().name(), - diagnostic.range().startOffset(), - diagnostic.range().endOffset(), - diagnostic.message()); - } -} diff --git a/prometeu-studio/src/main/java/p/studio/workspaces/editor/EditorInlineHintLayout.java b/prometeu-studio/src/main/java/p/studio/workspaces/editor/EditorInlineHintLayout.java deleted file mode 100644 index bab8e530..00000000 --- a/prometeu-studio/src/main/java/p/studio/workspaces/editor/EditorInlineHintLayout.java +++ /dev/null @@ -1,72 +0,0 @@ -package p.studio.workspaces.editor; - -import p.studio.lsp.dtos.LspInlineHintDTO; - -import java.util.ArrayList; -import java.util.List; -import java.util.Locale; -import java.util.Optional; - -final class EditorInlineHintLayout { - static final double HORIZONTAL_GAP = 6.0; - - private EditorInlineHintLayout() { - } - - static List layout( - final List inlineHints, - final AnchorBoundsResolver anchorBoundsResolver) { - final var placements = new ArrayList(); - for (final var inlineHint : inlineHints) { - final var anchorBounds = anchorBoundsResolver.resolve(inlineHint); - if (anchorBounds.isEmpty()) { - continue; - } - final var bounds = anchorBounds.orElseThrow(); - placements.add(new Placement( - inlineHint, - displayText(inlineHint), - categoryStyleClass(inlineHint), - bounds.maxX() + HORIZONTAL_GAP, - bounds.minY(), - bounds.height())); - } - return List.copyOf(placements); - } - - static String displayText(final LspInlineHintDTO inlineHint) { - return ": %s".formatted(inlineHint.label()); - } - - static String categoryStyleClass(final LspInlineHintDTO inlineHint) { - final var normalizedCategory = inlineHint.category() - .toLowerCase(Locale.ROOT) - .replaceAll("[^a-z0-9]+", "-") - .replaceAll("^-+", "") - .replaceAll("-+$", ""); - return normalizedCategory.isBlank() - ? "editor-inline-hint-generic" - : "editor-inline-hint-" + normalizedCategory; - } - - @FunctionalInterface - interface AnchorBoundsResolver { - Optional resolve(LspInlineHintDTO inlineHint); - } - - record AnchorBounds( - double minX, - double minY, - double maxX, - double height) { - } - - record Placement( - LspInlineHintDTO inlineHint, - String displayText, - String categoryStyleClass, - double screenX, - double screenY, - double anchorHeight) { - } -} diff --git a/prometeu-studio/src/main/java/p/studio/workspaces/editor/EditorInlineHintOverlay.java b/prometeu-studio/src/main/java/p/studio/workspaces/editor/EditorInlineHintOverlay.java deleted file mode 100644 index 039e716b..00000000 --- a/prometeu-studio/src/main/java/p/studio/workspaces/editor/EditorInlineHintOverlay.java +++ /dev/null @@ -1,124 +0,0 @@ -package p.studio.workspaces.editor; - -import javafx.application.Platform; -import javafx.geometry.Bounds; -import javafx.geometry.Point2D; -import javafx.scene.Node; -import javafx.scene.control.Label; -import javafx.scene.layout.Pane; -import org.fxmisc.richtext.CodeArea; -import org.reactfx.Subscription; -import p.studio.lsp.dtos.LspInlineHintDTO; - -import java.util.LinkedHashMap; -import java.util.List; -import java.util.Map; -import java.util.Objects; -import java.util.Optional; - -final class EditorInlineHintOverlay { - private final CodeArea codeArea; - private final Pane overlayPane = new Pane(); - private final Map labelsByHint = new LinkedHashMap<>(); - private final Subscription viewportSubscription; - private List inlineHints = List.of(); - - EditorInlineHintOverlay(final CodeArea codeArea) { - this.codeArea = Objects.requireNonNull(codeArea, "codeArea"); - overlayPane.setMouseTransparent(true); - overlayPane.setPickOnBounds(false); - overlayPane.getStyleClass().add("editor-inline-hint-layer"); - codeArea.estimatedScrollXProperty().addListener((ignored, previous, current) -> refresh()); - codeArea.estimatedScrollYProperty().addListener((ignored, previous, current) -> refresh()); - codeArea.layoutBoundsProperty().addListener((ignored, previous, current) -> refresh()); - codeArea.textProperty().addListener((ignored, previous, current) -> refresh()); - overlayPane.layoutBoundsProperty().addListener((ignored, previous, current) -> refresh()); - overlayPane.sceneProperty().addListener((ignored, previous, current) -> scheduleRefresh()); - viewportSubscription = codeArea.viewportDirtyEvents().subscribe(ignored -> refresh()); - } - - Node node() { - return overlayPane; - } - - void setInlineHints(final List inlineHints) { - this.inlineHints = List.copyOf(Objects.requireNonNull(inlineHints, "inlineHints")); - rebuildLabels(); - scheduleRefresh(); - } - - void clear() { - setInlineHints(List.of()); - } - - void refreshLater() { - scheduleRefresh(); - } - - void dispose() { - viewportSubscription.unsubscribe(); - } - - private void rebuildLabels() { - labelsByHint.clear(); - overlayPane.getChildren().clear(); - for (final var inlineHint : inlineHints) { - final var label = new Label(EditorInlineHintLayout.displayText(inlineHint)); - label.setManaged(false); - label.setMouseTransparent(true); - label.setPickOnBounds(false); - label.getStyleClass().add("editor-inline-hint"); - label.getStyleClass().add(EditorInlineHintLayout.categoryStyleClass(inlineHint)); - labelsByHint.put(inlineHint, label); - overlayPane.getChildren().add(label); - } - } - - private void scheduleRefresh() { - Platform.runLater(this::refresh); - } - - private void refresh() { - if (overlayPane.getScene() == null || inlineHints.isEmpty()) { - overlayPane.getChildren().forEach(node -> node.setVisible(false)); - return; - } - final var placements = EditorInlineHintLayout.layout(inlineHints, this::resolveAnchorBounds); - final var placedHints = new java.util.HashSet(); - for (final var placement : placements) { - final var label = labelsByHint.get(placement.inlineHint()); - if (label == null) { - continue; - } - label.applyCss(); - label.autosize(); - final Point2D localPoint = overlayPane.screenToLocal(placement.screenX(), placement.screenY()); - if (!Double.isFinite(localPoint.getX()) || !Double.isFinite(localPoint.getY())) { - label.setVisible(false); - continue; - } - final double layoutY = localPoint.getY() + Math.max(0.0d, (placement.anchorHeight() - label.getHeight()) / 2.0d); - label.relocate(localPoint.getX(), layoutY); - label.setVisible(true); - placedHints.add(placement.inlineHint()); - } - labelsByHint.forEach((inlineHint, label) -> { - if (!placedHints.contains(inlineHint)) { - label.setVisible(false); - } - }); - } - - private Optional resolveAnchorBounds(final LspInlineHintDTO inlineHint) { - if (codeArea.getLength() == 0) { - return Optional.empty(); - } - final int anchorOffset = Math.max(0, Math.min(codeArea.getLength(), inlineHint.anchor().endOffset())); - final Optional characterBounds = codeArea.getCharacterBoundsOnScreen(anchorOffset, anchorOffset); - return characterBounds.map(bounds -> new EditorInlineHintLayout.AnchorBounds( - bounds.getMinX(), - bounds.getMinY(), - bounds.getMaxX(), - bounds.getHeight())); - } -} diff --git a/prometeu-studio/src/main/java/p/studio/workspaces/editor/EditorInlineHintProjection.java b/prometeu-studio/src/main/java/p/studio/workspaces/editor/EditorInlineHintProjection.java deleted file mode 100644 index 63f010ac..00000000 --- a/prometeu-studio/src/main/java/p/studio/workspaces/editor/EditorInlineHintProjection.java +++ /dev/null @@ -1,159 +0,0 @@ -package p.studio.workspaces.editor; - -import org.fxmisc.richtext.model.StyleSpans; -import org.fxmisc.richtext.model.StyleSpansBuilder; -import org.fxmisc.richtext.model.StyleSpan; -import p.studio.lsp.dtos.LspInlineHintDTO; - -import java.util.ArrayList; -import java.util.Collection; -import java.util.Comparator; -import java.util.LinkedHashSet; -import java.util.List; -import java.util.Objects; - -final class EditorInlineHintProjection { - private final String displayText; - private final StyleSpans> displayStyles; - private final List protectedRanges; - - private EditorInlineHintProjection( - final String displayText, - final StyleSpans> displayStyles, - final List protectedRanges) { - this.displayText = Objects.requireNonNull(displayText, "displayText"); - this.displayStyles = Objects.requireNonNull(displayStyles, "displayStyles"); - this.protectedRanges = new ArrayList<>(Objects.requireNonNull(protectedRanges, "protectedRanges")); - } - - static EditorInlineHintProjection create( - final String sourceText, - final StyleSpans> sourceStyles, - final List inlineHints) { - Objects.requireNonNull(sourceText, "sourceText"); - Objects.requireNonNull(sourceStyles, "sourceStyles"); - Objects.requireNonNull(inlineHints, "inlineHints"); - if (inlineHints.isEmpty()) { - return new EditorInlineHintProjection(sourceText, sourceStyles, List.of()); - } - - final var sortedHints = inlineHints.stream() - .sorted(Comparator.comparingInt(hint -> hint.anchor().endOffset())) - .toList(); - final var displayText = new StringBuilder(sourceText.length() + (sortedHints.size() * 8)); - final var displayStyles = new StyleSpansBuilder>(); - final var protectedRanges = new ArrayList(); - - int sourceOffset = 0; - int displayOffset = 0; - for (final var inlineHint : sortedHints) { - final int anchorOffset = Math.max(0, Math.min(sourceText.length(), inlineHint.anchor().endOffset())); - if (anchorOffset > sourceOffset) { - displayText.append(sourceText, sourceOffset, anchorOffset); - appendSourceStyles(displayStyles, sourceStyles.subView(sourceOffset, anchorOffset)); - displayOffset += anchorOffset - sourceOffset; - sourceOffset = anchorOffset; - } - - final String hintText = " " + EditorInlineHintLayout.displayText(inlineHint); - displayText.append(hintText); - displayStyles.add(hintClasses(inlineHint), hintText.length()); - protectedRanges.add(new ProtectedRange(displayOffset, displayOffset + hintText.length())); - displayOffset += hintText.length(); - } - - if (sourceOffset < sourceText.length()) { - displayText.append(sourceText, sourceOffset, sourceText.length()); - appendSourceStyles(displayStyles, sourceStyles.subView(sourceOffset, sourceText.length())); - } - return new EditorInlineHintProjection(displayText.toString(), displayStyles.create(), protectedRanges); - } - - String displayText() { - return displayText; - } - - StyleSpans> displayStyles() { - return displayStyles; - } - - String stripDecorations(final String currentDisplayText) { - Objects.requireNonNull(currentDisplayText, "currentDisplayText"); - if (protectedRanges.isEmpty()) { - return currentDisplayText; - } - final var sourceText = new StringBuilder(currentDisplayText); - for (int index = protectedRanges.size() - 1; index >= 0; index--) { - final var range = protectedRanges.get(index); - final int start = Math.max(0, Math.min(sourceText.length(), range.start())); - final int end = Math.max(start, Math.min(sourceText.length(), range.end())); - sourceText.delete(start, end); - } - return sourceText.toString(); - } - - void applyDisplayChange(final int position, final int removedLength, final int insertedLength) { - final int delta = insertedLength - removedLength; - for (int index = 0; index < protectedRanges.size(); index++) { - final var range = protectedRanges.get(index); - if (range.end() <= position) { - continue; - } - if (range.start() >= position + removedLength) { - protectedRanges.set(index, range.shift(delta)); - continue; - } - protectedRanges.set(index, range); - } - } - - boolean containsOffset(final int offset) { - return protectedRanges.stream().anyMatch(range -> range.contains(offset)); - } - - boolean touchesRange(final int start, final int end) { - if (start == end) { - return containsOffset(start); - } - return protectedRanges.stream().anyMatch(range -> range.intersects(start, end)); - } - - int clampCaret(final int offset, final boolean preferRightBoundary) { - for (final var range : protectedRanges) { - if (!range.contains(offset)) { - continue; - } - return preferRightBoundary ? range.end() : range.start(); - } - return offset; - } - - private static void appendSourceStyles( - final StyleSpansBuilder> builder, - final StyleSpans> styles) { - for (final StyleSpan> span : styles) { - builder.add(span.getStyle(), span.getLength()); - } - } - - private static Collection hintClasses(final LspInlineHintDTO inlineHint) { - final var classes = new LinkedHashSet(); - classes.add("editor-inline-hint"); - classes.add(EditorInlineHintLayout.categoryStyleClass(inlineHint)); - return List.copyOf(classes); - } - - record ProtectedRange(int start, int end) { - boolean contains(final int offset) { - return offset >= start && offset < end; - } - - boolean intersects(final int rangeStart, final int rangeEnd) { - return rangeStart < end && rangeEnd > start; - } - - ProtectedRange shift(final int delta) { - return new ProtectedRange(start + delta, end + delta); - } - } -} diff --git a/prometeu-studio/src/main/java/p/studio/workspaces/editor/EditorOpenFileBuffer.java b/prometeu-studio/src/main/java/p/studio/workspaces/editor/EditorOpenFileBuffer.java deleted file mode 100644 index 62e491f7..00000000 --- a/prometeu-studio/src/main/java/p/studio/workspaces/editor/EditorOpenFileBuffer.java +++ /dev/null @@ -1,37 +0,0 @@ -package p.studio.workspaces.editor; - -import p.studio.vfs.messages.VfsDocumentAccessMode; - -import java.nio.file.Path; -import java.util.Objects; - -public record EditorOpenFileBuffer( - Path path, - String tabLabel, - String typeId, - String content, - String lineSeparator, - boolean frontendDocument, - VfsDocumentAccessMode accessMode, - boolean dirty) { - public EditorOpenFileBuffer { - path = Objects.requireNonNull(path, "path").toAbsolutePath().normalize(); - tabLabel = Objects.requireNonNull(tabLabel, "tabLabel"); - typeId = Objects.requireNonNull(typeId, "typeId"); - content = Objects.requireNonNull(content, "content"); - lineSeparator = Objects.requireNonNull(lineSeparator, "lineSeparator"); - Objects.requireNonNull(accessMode, "accessMode"); - } - - public boolean editable() { - return accessMode == VfsDocumentAccessMode.EDITABLE; - } - - public boolean readOnly() { - return !editable(); - } - - public boolean saveEnabled() { - return editable() && dirty; - } -} diff --git a/prometeu-studio/src/main/java/p/studio/workspaces/editor/EditorOpenFileSession.java b/prometeu-studio/src/main/java/p/studio/workspaces/editor/EditorOpenFileSession.java deleted file mode 100644 index b1e4bdb0..00000000 --- a/prometeu-studio/src/main/java/p/studio/workspaces/editor/EditorOpenFileSession.java +++ /dev/null @@ -1,112 +0,0 @@ -package p.studio.workspaces.editor; - -import p.studio.projectstate.ProjectLocalStudioState; - -import java.nio.file.Path; -import java.util.ArrayList; -import java.util.List; -import java.util.Objects; -import java.util.Optional; - -public final class EditorOpenFileSession { - private final List openFiles = new ArrayList<>(); - private Path activePath; - - public void open(final EditorOpenFileBuffer fileBuffer) { - final var buffer = Objects.requireNonNull(fileBuffer, "fileBuffer"); - final var existingIndex = indexOf(buffer.path()); - if (existingIndex < 0) { - openFiles.add(buffer); - } else { - openFiles.set(existingIndex, buffer); - } - activePath = buffer.path(); - } - - public void activate(final Path path) { - final var normalizedPath = normalize(path); - if (find(normalizedPath).isPresent()) { - activePath = normalizedPath; - } - } - - public void close(final Path path) { - final int index = indexOf(path); - if (index < 0) { - return; - } - final Path normalizedPath = normalize(path); - openFiles.remove(index); - if (openFiles.isEmpty()) { - activePath = null; - return; - } - if (!normalizedPath.equals(activePath)) { - return; - } - final int nextIndex = Math.min(index, openFiles.size() - 1); - activePath = openFiles.get(nextIndex).path(); - } - - public List openFiles() { - return List.copyOf(openFiles); - } - - public Optional activeFile() { - if (activePath == null) { - return Optional.empty(); - } - return find(activePath); - } - - public Optional file(final Path path) { - return find(normalize(path)); - } - - public boolean hasDirtyEditableFiles() { - return openFiles.stream().anyMatch(EditorOpenFileBuffer::saveEnabled); - } - - public boolean hasSaveableActiveFile() { - return activeFile().map(EditorOpenFileBuffer::saveEnabled).orElse(false); - } - - public boolean isEmpty() { - return openFiles.isEmpty(); - } - - public void clear() { - openFiles.clear(); - activePath = null; - } - - public ProjectLocalStudioState.EditorRestorationState restorationState() { - return new ProjectLocalStudioState.EditorRestorationState( - openFiles.stream() - .map(buffer -> buffer.path().toString()) - .toList(), - activePath == null ? null : activePath.toString()); - } - - private Optional find(final Path path) { - final int index = indexOf(path); - if (index < 0) { - return Optional.empty(); - } - return Optional.of(openFiles.get(index)); - } - - private int indexOf(final Path path) { - final var normalizedPath = normalize(path); - for (int index = 0; index < openFiles.size(); index++) { - if (openFiles.get(index).path().equals(normalizedPath)) { - return index; - } - } - return -1; - } - - private Path normalize(final Path path) { - return Objects.requireNonNull(path, "path").toAbsolutePath().normalize(); - } -} diff --git a/prometeu-studio/src/main/java/p/studio/workspaces/editor/EditorOutlinePanel.java b/prometeu-studio/src/main/java/p/studio/workspaces/editor/EditorOutlinePanel.java deleted file mode 100644 index 2432a6d6..00000000 --- a/prometeu-studio/src/main/java/p/studio/workspaces/editor/EditorOutlinePanel.java +++ /dev/null @@ -1,116 +0,0 @@ -package p.studio.workspaces.editor; - -import javafx.geometry.Insets; -import javafx.scene.control.Label; -import javafx.scene.control.ScrollPane; -import javafx.scene.layout.VBox; -import p.studio.lsp.dtos.LspSymbolDTO; -import p.studio.lsp.messages.LspSymbolKind; -import p.studio.Container; -import p.studio.controls.WorkspaceDockPane; -import p.studio.utilities.i18n.I18n; - -import java.nio.file.Path; -import java.util.List; - -public final class EditorOutlinePanel extends WorkspaceDockPane { - private static final double COLLAPSED_HEIGHT = 34.0; - private static final double MINIMUM_EXPANDED_HEIGHT = 120.0; - private static final double DEFAULT_HEIGHT = 180.0; - private final Label summary = new Label(); - private final VBox symbolsBox = new VBox(6); - - public EditorOutlinePanel() { - super( - Container.i18n().bind(I18n.CODE_EDITOR_OUTLINE_TITLE), - COLLAPSED_HEIGHT, - MINIMUM_EXPANDED_HEIGHT, - DEFAULT_HEIGHT, - true, - "editor-workspace-outline-panel"); - - summary.getStyleClass().addAll("editor-workspace-placeholder", "editor-workspace-outline-summary"); - summary.setWrapText(true); - - final var symbolsTitle = sectionTitle(I18n.CODE_EDITOR_OUTLINE_SYMBOLS); - - symbolsBox.getStyleClass().add("editor-workspace-outline-list"); - - final var content = new VBox(10, - summary, - symbolsTitle, - symbolsBox); - content.getStyleClass().add("editor-workspace-panel-content"); - content.setPadding(new Insets(10, 16, 14, 16)); - final var scrollPane = new ScrollPane(content); - scrollPane.setFitToWidth(true); - scrollPane.getStyleClass().add("editor-workspace-outline-scroll"); - setDockContent(scrollPane); - showPlaceholder(); - } - - public void showPlaceholder() { - summary.textProperty().unbind(); - summary.textProperty().bind(Container.i18n().bind(I18n.CODE_EDITOR_OUTLINE_PLACEHOLDER)); - symbolsBox.getChildren().setAll(placeholderLabel(I18n.CODE_EDITOR_OUTLINE_EMPTY_SYMBOLS)); - } - - public void showSemanticReadResult( - final Path documentPath, - final List symbols) { - summary.textProperty().unbind(); - summary.setText(documentPath.getFileName() + " • semantic read-only"); - rebuildSymbols(symbols); - } - - private void rebuildSymbols(final List symbols) { - symbolsBox.getChildren().clear(); - int visible = 0; - for (final LspSymbolDTO symbol : symbols) { - visible += appendSymbol(symbol, 0); - } - if (visible == 0) { - symbolsBox.getChildren().add(placeholderLabel(I18n.CODE_EDITOR_OUTLINE_EMPTY_SYMBOLS)); - } - } - - private int appendSymbol(final LspSymbolDTO symbol, final int depth) { - int visible = 0; - int childDepth = depth; - if (showInOutline(symbol.kind())) { - final var label = new Label(symbol.name() + " • " + symbol.kind().name().toLowerCase()); - label.setWrapText(true); - label.setPadding(new Insets(0, 0, 0, depth * 12)); - label.getStyleClass().add("editor-workspace-outline-item"); - symbolsBox.getChildren().add(label); - visible++; - childDepth++; - } - for (final LspSymbolDTO child : symbol.children()) { - visible += appendSymbol(child, childDepth); - } - return visible; - } - - private boolean showInOutline(final LspSymbolKind kind) { - return switch (kind) { - case IF, SWITCH, FOR, WHILE, HANDLE -> false; - default -> true; - }; - } - - private Label sectionTitle(final I18n key) { - final var label = new Label(); - label.textProperty().bind(Container.i18n().bind(key)); - label.getStyleClass().add("editor-workspace-outline-section-title"); - return label; - } - - private Label placeholderLabel(final I18n key) { - final var label = new Label(); - label.textProperty().bind(Container.i18n().bind(key)); - label.setWrapText(true); - label.getStyleClass().addAll("editor-workspace-placeholder", "editor-workspace-outline-item"); - return label; - } -} diff --git a/prometeu-studio/src/main/java/p/studio/workspaces/editor/EditorProjectNavigatorPanel.java b/prometeu-studio/src/main/java/p/studio/workspaces/editor/EditorProjectNavigatorPanel.java deleted file mode 100644 index bbcb13a8..00000000 --- a/prometeu-studio/src/main/java/p/studio/workspaces/editor/EditorProjectNavigatorPanel.java +++ /dev/null @@ -1,337 +0,0 @@ -package p.studio.workspaces.editor; - -import javafx.geometry.Insets; -import javafx.scene.Node; -import javafx.scene.control.Button; -import javafx.scene.control.Label; -import javafx.scene.control.Tooltip; -import javafx.scene.control.TreeCell; -import javafx.scene.control.TreeItem; -import javafx.scene.control.TreeView; -import javafx.scene.layout.BorderPane; -import javafx.scene.layout.HBox; -import javafx.scene.layout.Priority; -import javafx.scene.layout.Region; -import javafx.scene.layout.StackPane; -import p.studio.Container; -import p.studio.utilities.i18n.I18n; -import p.studio.vfs.messages.VfsProjectNode; -import p.studio.vfs.messages.VfsProjectSnapshot; - -import java.nio.file.Path; -import java.util.LinkedHashSet; -import java.util.HashSet; -import java.util.List; -import java.util.Objects; -import java.util.Optional; -import java.util.Set; -import java.util.function.Consumer; - -public final class EditorProjectNavigatorPanel extends BorderPane { - private final Button revealActiveButton = new Button(); - private final Button refreshButton = new Button(); - private final TreeView treeView = new TreeView<>(); - private final Label emptyState = emptyLabel(); - private final StackPane content = new StackPane(); - private Runnable revealActiveFileAction = () -> { }; - private Runnable refreshAction = () -> { }; - private Consumer fileSelectionAction = node -> { }; - private Set preferredExpandedPaths = Set.of(); - - public EditorProjectNavigatorPanel() { - getStyleClass().addAll("editor-workspace-panel", "editor-workspace-navigator-panel"); - setPadding(new Insets(14, 16, 14, 16)); - setTop(buildHeader()); - configureTreeView(); - content.getStyleClass().add("editor-workspace-panel-content"); - content.getChildren().addAll(treeView, emptyState); - setCenter(content); - showEmptyState(true); - } - - private HBox buildHeader() { - final var title = new Label(); - title.textProperty().bind(Container.i18n().bind(I18n.CODE_EDITOR_NAVIGATOR_TITLE)); - title.getStyleClass().add("editor-workspace-panel-title"); - - revealActiveButton.setFocusTraversable(false); - revealActiveButton.setDisable(true); - revealActiveButton.getStyleClass().addAll( - "studio-button", - "studio-button-icon", - "editor-workspace-header-icon-button"); - revealActiveButton.setGraphic(EditorWorkspaceIcons.target()); - revealActiveButton.setTooltip(new Tooltip(Container.i18n().text(I18n.CODE_EDITOR_NAVIGATOR_REVEAL_ACTIVE))); - revealActiveButton.setOnAction(event -> revealActiveFileAction.run()); - - refreshButton.setFocusTraversable(false); - refreshButton.getStyleClass().addAll( - "studio-button", - "studio-button-icon", - "editor-workspace-header-icon-button"); - refreshButton.setGraphic(EditorWorkspaceIcons.refresh()); - refreshButton.setTooltip(new Tooltip(Container.i18n().text(I18n.CODE_EDITOR_NAVIGATOR_REFRESH))); - refreshButton.setOnAction(event -> refreshAction.run()); - - final var spacer = new Region(); - HBox.setHgrow(spacer, Priority.ALWAYS); - - final var header = new HBox(8, title, spacer, revealActiveButton, refreshButton); - header.getStyleClass().add("editor-workspace-panel-header"); - return header; - } - - private void configureTreeView() { - treeView.getStyleClass().add("editor-workspace-tree"); - treeView.setShowRoot(true); - treeView.setFocusTraversable(false); - treeView.setCellFactory(ignored -> new TreeCell<>() { - @Override - protected void updateItem(final VfsProjectNode item, final boolean empty) { - super.updateItem(item, empty); - getStyleClass().remove("editor-workspace-tree-cell-tagged"); - getStyleClass().remove("editor-workspace-tree-cell-root"); - if (empty || item == null) { - setText(null); - setGraphic(null); - return; - } - setText(labelFor(item, getTreeItem())); - setGraphic(iconFor(item, getTreeItem())); - if (isRoot(getTreeItem())) { - getStyleClass().add("editor-workspace-tree-cell-root"); - } - if (item.taggedSourceRoot() || isInsideTaggedSourceRoot(getTreeItem())) { - getStyleClass().add("editor-workspace-tree-cell-tagged"); - } - } - }); - treeView.setOnMouseClicked(event -> { - if (event.getClickCount() != 2) { - return; - } - final TreeItem current = treeView.getSelectionModel().getSelectedItem(); - if (current == null || current.getValue() == null || current.getValue().directory()) { - return; - } - fileSelectionAction.accept(current.getValue()); - }); - } - - public void setRefreshAction(final Runnable refreshAction) { - this.refreshAction = Objects.requireNonNull(refreshAction, "refreshAction"); - } - - public void setRevealActiveFileAction(final Runnable revealActiveFileAction) { - this.revealActiveFileAction = Objects.requireNonNull(revealActiveFileAction, "revealActiveFileAction"); - } - - public void setRevealActiveFileAvailable(final boolean available) { - revealActiveButton.setDisable(!available); - } - - public void setFileSelectionAction(final Consumer fileSelectionAction) { - this.fileSelectionAction = Objects.requireNonNull(fileSelectionAction, "fileSelectionAction"); - } - - public void setSnapshot(final VfsProjectSnapshot snapshot) { - final var currentSelection = selectedPath(); - final var expandedPaths = mergeExpandedPaths(); - final var rootItem = buildTreeItem(Objects.requireNonNull(snapshot, "snapshot").rootNode(), expandedPaths, true); - treeView.setRoot(rootItem); - restoreSelection(rootItem, currentSelection); - showEmptyState(false); - } - - public List expandedPathStrings() { - return captureExpandedPaths(treeView.getRoot()).stream() - .map(Path::toString) - .toList(); - } - - public void restoreExpandedPaths(final List expandedPaths) { - final LinkedHashSet restored = new LinkedHashSet<>(); - if (expandedPaths != null) { - for (final String expandedPath : expandedPaths) { - if (expandedPath == null || expandedPath.isBlank()) { - continue; - } - try { - restored.add(Path.of(expandedPath).toAbsolutePath().normalize()); - } catch (RuntimeException ignored) { - // Ignore malformed persisted paths and continue with the remaining ones. - } - } - } - preferredExpandedPaths = Set.copyOf(restored); - final TreeItem rootItem = treeView.getRoot(); - if (rootItem != null) { - final var currentSelection = selectedPath(); - treeView.setRoot(buildTreeItem(rootItem.getValue(), preferredExpandedPaths, true)); - restoreSelection(treeView.getRoot(), currentSelection); - } - } - - public void revealPath(final Path path) { - final var normalizedPath = Objects.requireNonNull(path, "path").toAbsolutePath().normalize(); - final var rootItem = treeView.getRoot(); - if (rootItem == null) { - return; - } - findTreeItem(rootItem, normalizedPath).ifPresent(item -> { - expandAncestors(item); - treeView.getSelectionModel().select(item); - treeView.scrollTo(Math.max(treeView.getRow(item) - 2, 0)); - }); - } - - private TreeItem buildTreeItem( - final VfsProjectNode node, - final Set expandedPaths, - final boolean isRoot) { - final TreeItem item = node.directory() - ? new DirectoryTreeItem(node) - : new TreeItem<>(node); - item.setExpanded(isRoot || expandedPaths.contains(node.path())); - node.children().stream() - .map(child -> buildTreeItem(child, expandedPaths, false)) - .forEach(item.getChildren()::add); - return item; - } - - private Set captureExpandedPaths(final TreeItem item) { - final var expandedPaths = new HashSet(); - if (item == null) { - return expandedPaths; - } - collectExpandedPaths(item, expandedPaths); - return expandedPaths; - } - - private void collectExpandedPaths(final TreeItem item, final Set expandedPaths) { - final var value = item.getValue(); - if (value != null && item.isExpanded()) { - expandedPaths.add(value.path()); - } - item.getChildren().forEach(child -> collectExpandedPaths(child, expandedPaths)); - } - - private Set mergeExpandedPaths() { - final LinkedHashSet merged = new LinkedHashSet<>(preferredExpandedPaths); - merged.addAll(captureExpandedPaths(treeView.getRoot())); - return Set.copyOf(merged); - } - - private Optional selectedPath() { - return Optional.ofNullable(treeView.getSelectionModel().getSelectedItem()) - .map(TreeItem::getValue) - .map(VfsProjectNode::path); - } - - private void restoreSelection(final TreeItem rootItem, final Optional selectedPath) { - treeView.getSelectionModel().clearSelection(); - if (selectedPath.isEmpty()) { - return; - } - findTreeItem(rootItem, selectedPath.orElseThrow()) - .ifPresent(item -> treeView.getSelectionModel().select(item)); - } - - private Optional> findTreeItem(final TreeItem item, final Path path) { - if (item == null || item.getValue() == null) { - return Optional.empty(); - } - if (item.getValue().path().equals(path)) { - return Optional.of(item); - } - for (final var child : item.getChildren()) { - final var match = findTreeItem(child, path); - if (match.isPresent()) { - return match; - } - } - return Optional.empty(); - } - - private void showEmptyState(final boolean empty) { - treeView.setVisible(!empty); - treeView.setManaged(!empty); - emptyState.setVisible(empty); - emptyState.setManaged(empty); - } - - private void expandAncestors(final TreeItem item) { - TreeItem current = item; - while (current != null) { - current.setExpanded(true); - current = current.getParent(); - } - } - - private Node iconFor(final VfsProjectNode node, final TreeItem treeItem) { - if (node.directory()) { - if (isBuildTone(node)) { - return EditorWorkspaceIcons.folderBuild(); - } - if (node.taggedSourceRoot() || isInsideTaggedSourceRoot(treeItem)) { - return EditorWorkspaceIcons.folderSource(); - } - return EditorWorkspaceIcons.folderDefault(); - } - if ("prometeu.json".equals(node.displayName())) { - return EditorWorkspaceIcons.cog(); - } - - return EditorWorkspaceIcons.file(); - } - - private String labelFor(final VfsProjectNode node, final TreeItem treeItem) { - if (!isRoot(treeItem)) { - return node.displayName(); - } - final var directoryName = Optional.ofNullable(node.path().getFileName()) - .map(Path::toString) - .filter(name -> !name.isBlank()) - .orElse(node.displayName()); - return directoryName + " (" + node.displayName() + ")"; - } - - private boolean isInsideTaggedSourceRoot(final TreeItem item) { - var current = item == null ? null : item.getParent(); - while (current != null && current.getValue() != null) { - if (current.getValue().taggedSourceRoot()) { - return true; - } - current = current.getParent(); - } - return false; - } - - private boolean isRoot(final TreeItem item) { - return item != null && item.getParent() == null; - } - - private boolean isBuildTone(final VfsProjectNode node) { - return node.directory() - && ("build".equals(node.displayName()) || "cartridge".equals(node.displayName())); - } - - private Label emptyLabel() { - final var placeholder = new Label(); - placeholder.textProperty().bind(Container.i18n().bind(I18n.CODE_EDITOR_NAVIGATOR_PLACEHOLDER)); - placeholder.getStyleClass().add("editor-workspace-placeholder"); - placeholder.setWrapText(true); - return placeholder; - } - - private static final class DirectoryTreeItem extends TreeItem { - private DirectoryTreeItem(final VfsProjectNode node) { - super(node); - } - - @Override - public boolean isLeaf() { - return false; - } - } -} diff --git a/prometeu-studio/src/main/java/p/studio/workspaces/editor/EditorStatusBar.java b/prometeu-studio/src/main/java/p/studio/workspaces/editor/EditorStatusBar.java deleted file mode 100644 index dde4b197..00000000 --- a/prometeu-studio/src/main/java/p/studio/workspaces/editor/EditorStatusBar.java +++ /dev/null @@ -1,218 +0,0 @@ -package p.studio.workspaces.editor; - -import javafx.geometry.Pos; -import javafx.scene.Node; -import javafx.scene.control.Label; -import javafx.scene.layout.HBox; -import javafx.scene.layout.Priority; -import javafx.scene.layout.Region; -import javafx.scene.layout.StackPane; -import p.studio.Container; -import p.studio.projects.ProjectReference; -import p.studio.utilities.i18n.I18n; - -import java.nio.file.Path; -import java.util.Optional; - -public final class EditorStatusBar extends HBox { - private final HBox breadcrumb = new HBox(6); - private final Label position = new Label(); - private final Label lineSeparator = new Label(); - private final Label indentation = new Label(); - private final Label language = new Label(); - private final StackPane accessMode = new StackPane(); - - public EditorStatusBar() { - setAlignment(Pos.CENTER_LEFT); - setSpacing(8); - getStyleClass().add("editor-workspace-status-bar"); - - breadcrumb.getStyleClass().add("editor-workspace-status-breadcrumb"); - breadcrumb.setAlignment(Pos.CENTER_LEFT); - - final var spacer = new Region(); - HBox.setHgrow(spacer, Priority.ALWAYS); - - styleChip(position); - position.getStyleClass().add("editor-workspace-status-chip-position"); - styleChip(lineSeparator); - lineSeparator.getStyleClass().add("editor-workspace-status-chip-line-separator"); - styleChip(indentation); - indentation.getStyleClass().add("editor-workspace-status-chip-indentation"); - styleChip(language); - language.getStyleClass().add("editor-workspace-status-chip-language"); - accessMode.getStyleClass().addAll("editor-workspace-status-chip", "editor-workspace-status-chip-access-mode"); - - getChildren().addAll( - breadcrumb, - spacer, - position, - lineSeparator, - indentation, - language, - accessMode - ); - - } - - public void showFile( - final ProjectReference projectReference, - final EditorOpenFileBuffer fileBuffer, - final EditorDocumentPresentation presentation, - final String indentationPolicyLabel) { - showBreadcrumb(projectReference, fileBuffer.path()); - showMetadata(true); - showPosition(fileBuffer.editable(), 1, 1); - showDocumentFormatting(fileBuffer.lineSeparator(), indentationPolicyLabel); - setText(language, fileBuffer.typeId()); - EditorDocumentPresentationStyles.applyToStatusChip(language, presentation); - showAccessMode(fileBuffer.readOnly()); - } - - public void showPlaceholder(final EditorDocumentPresentation presentation) { - breadcrumb.getChildren().clear(); - showMetadata(false); - showPosition(false, 1, 1); - bindDefault(lineSeparator, I18n.CODE_EDITOR_STATUS_LINE_SEPARATOR); - bindDefault(indentation, I18n.CODE_EDITOR_STATUS_INDENTATION); - bindDefault(language, I18n.CODE_EDITOR_STATUS_LANGUAGE); - EditorDocumentPresentationStyles.applyToStatusChip(language, presentation); - accessMode.getChildren().clear(); - accessMode.getStyleClass().removeAll("editor-workspace-status-chip-editable", "editor-workspace-status-chip-read-only"); - } - - public void showCaretPosition(final int line, final int column) { - if (!position.isManaged()) { - return; - } - setText(position, line + ":" + column); - } - - public void showDocumentFormatting(final String separator, final String indentationPolicyLabel) { - setText(lineSeparator, separator); - setText(indentation, indentationPolicyLabel); - } - - private void bindDefault(final Label label, final I18n key) { - bindText(label, key); - } - - private void bindText(final Label label, final I18n key) { - label.textProperty().unbind(); - label.textProperty().bind(Container.i18n().bind(key)); - } - - private void showBreadcrumb(final ProjectReference projectReference, final Path filePath) { - breadcrumb.getChildren().clear(); - breadcrumb.getChildren().add(segment( - rootLabel(projectReference), - EditorWorkspaceIcons.folderDefault(), - true)); - - final var relativePath = projectReference.rootPath() - .toAbsolutePath() - .normalize() - .relativize(filePath.toAbsolutePath().normalize()); - - boolean insideSourceTree = false; - Path accumulated = projectReference.rootPath().toAbsolutePath().normalize(); - for (int index = 0; index < relativePath.getNameCount(); index++) { - final var part = relativePath.getName(index).toString(); - accumulated = accumulated.resolve(part); - final boolean isLast = index == relativePath.getNameCount() - 1; - if ("src".equals(part)) { - insideSourceTree = true; - } - breadcrumb.getChildren().add(separator()); - breadcrumb.getChildren().add(segment( - part, - iconForSegment(part, isLast, insideSourceTree), - false)); - } - } - - private String rootLabel(final ProjectReference projectReference) { - return Optional.ofNullable(projectReference.rootPath().getFileName()) - .map(Path::toString) - .filter(name -> !name.isBlank()) - .orElse(projectReference.name()); - } - - private HBox segment(final String text, final Node icon, final boolean root) { - final var label = new Label(text); - label.getStyleClass().add("editor-workspace-status-breadcrumb-text"); - - final var box = new HBox(6, icon, label); - box.setAlignment(Pos.CENTER_LEFT); - box.getStyleClass().add("editor-workspace-status-breadcrumb-segment"); - if (root) { - box.getStyleClass().add("editor-workspace-status-breadcrumb-segment-root"); - } - return box; - } - - private Label separator() { - final var label = new Label(">"); - label.getStyleClass().add("editor-workspace-status-breadcrumb-separator"); - return label; - } - - private Node iconForSegment(final String name, final boolean isFile, final boolean insideSourceTree) { - if (isFile) { - if ("prometeu.json".equals(name)) { - return EditorWorkspaceIcons.cog(); - } - return EditorWorkspaceIcons.file(); - } - - if ("build".equals(name) || "cartridge".equals(name)) { - return EditorWorkspaceIcons.folderBuild(); - } - if ("src".equals(name) || insideSourceTree) { - return EditorWorkspaceIcons.folderSource(); - } - return EditorWorkspaceIcons.folderDefault(); - } - - private void setText(final Label label, final String text) { - label.textProperty().unbind(); - label.setText(text); - } - - private void showMetadata(final boolean visible) { - setVisibleManaged(lineSeparator, visible); - setVisibleManaged(indentation, visible); - setVisibleManaged(language, visible); - setVisibleManaged(accessMode, visible); - } - - private void showPosition(final boolean visible, final int line, final int column) { - setVisibleManaged(position, visible); - if (!visible) { - bindDefault(position, I18n.CODE_EDITOR_STATUS_POSITION); - return; - } - setText(position, line + ":" + column); - } - - private void showAccessMode(final boolean readOnlyMode) { - accessMode.getChildren().setAll(readOnlyMode - ? EditorWorkspaceIcons.lockClosed() - : EditorWorkspaceIcons.lockOpen()); - accessMode.getStyleClass().removeAll("editor-workspace-status-chip-editable", "editor-workspace-status-chip-read-only"); - accessMode.getStyleClass().add(readOnlyMode - ? "editor-workspace-status-chip-read-only" - : "editor-workspace-status-chip-editable"); - } - - private void setVisibleManaged(final Node node, final boolean visible) { - node.setVisible(visible); - node.setManaged(visible); - } - - private void styleChip(final Label label) { - if (!label.getStyleClass().contains("editor-workspace-status-chip")) { - label.getStyleClass().add("editor-workspace-status-chip"); - } - } -} diff --git a/prometeu-studio/src/main/java/p/studio/workspaces/editor/EditorTabStrip.java b/prometeu-studio/src/main/java/p/studio/workspaces/editor/EditorTabStrip.java deleted file mode 100644 index 84dc590e..00000000 --- a/prometeu-studio/src/main/java/p/studio/workspaces/editor/EditorTabStrip.java +++ /dev/null @@ -1,252 +0,0 @@ -package p.studio.workspaces.editor; - -import javafx.css.PseudoClass; -import javafx.geometry.Pos; -import javafx.scene.control.Button; -import javafx.scene.control.CustomMenuItem; -import javafx.scene.control.Label; -import javafx.scene.control.MenuButton; -import javafx.scene.control.MenuItem; -import javafx.scene.control.OverrunStyle; -import javafx.scene.input.MouseButton; -import javafx.scene.input.MouseEvent; -import javafx.scene.layout.HBox; -import javafx.scene.layout.Priority; -import javafx.scene.layout.Region; -import javafx.scene.layout.StackPane; -import javafx.scene.shape.SVGPath; -import p.studio.Container; -import p.studio.utilities.i18n.I18n; - -import java.nio.file.Path; -import java.util.ArrayList; -import java.util.List; -import java.util.Objects; -import java.util.function.Consumer; - -public final class EditorTabStrip extends HBox { - private static final PseudoClass PRESSED_PSEUDO_CLASS = PseudoClass.getPseudoClass("pressed"); - private static final double TAB_WIDTH_HINT = 176.0; - private static final double TAB_HEIGHT_HINT = 34.0; - private static final double STRIP_HEIGHT_HINT = 50.0; - private static final double OVERFLOW_WIDTH_HINT = 128.0; - private static final double OVERFLOW_MENU_WIDTH_HINT = 180.0; - - private final MenuButton overflowButton = new MenuButton(); - private final Region spacer = new Region(); - private final List openFiles = new ArrayList<>(); - private Consumer tabSelectionAction = path -> { }; - private Consumer tabCloseAction = path -> { }; - private Path activePath; - - public EditorTabStrip() { - setAlignment(Pos.CENTER_LEFT); - setSpacing(10); - getStyleClass().add("editor-workspace-tab-strip"); - setMinHeight(STRIP_HEIGHT_HINT); - setPrefHeight(STRIP_HEIGHT_HINT); - setMaxHeight(STRIP_HEIGHT_HINT); - HBox.setHgrow(spacer, Priority.ALWAYS); - - overflowButton.textProperty().bind(Container.i18n().bind(I18n.CODE_EDITOR_TABS_OVERFLOW)); - overflowButton.setFocusTraversable(false); - overflowButton.getStyleClass().addAll( - "studio-button", - "studio-button-secondary", - "editor-workspace-tab-overflow"); - applyOverflowMetrics(); - widthProperty().addListener((ignored, previous, current) -> rebuild()); - rebuild(); - } - - public void setTabSelectionAction(final Consumer tabSelectionAction) { - this.tabSelectionAction = Objects.requireNonNull(tabSelectionAction, "tabSelectionAction"); - } - - public void setTabCloseAction(final Consumer tabCloseAction) { - this.tabCloseAction = Objects.requireNonNull(tabCloseAction, "tabCloseAction"); - } - - public void showOpenFiles(final List files, final Path activePath) { - this.openFiles.clear(); - this.openFiles.addAll(Objects.requireNonNull(files, "files")); - this.activePath = activePath == null ? null : activePath.toAbsolutePath().normalize(); - rebuild(); - } - - private void rebuild() { - getChildren().clear(); - if (openFiles.isEmpty()) { - overflowButton.getItems().clear(); - getChildren().add(spacer); - overflowButton.setVisible(false); - overflowButton.setManaged(false); - return; - } - - final int visibleCount = visibleCount(); - final int activeIndex = activeIndex(); - final int startIndex = Math.max(0, Math.min(activeIndex - visibleCount + 1, openFiles.size() - visibleCount)); - final int endIndex = Math.min(openFiles.size(), startIndex + visibleCount); - - for (int index = startIndex; index < endIndex; index++) { - final var fileBuffer = openFiles.get(index); - final var tabButton = new Button(fileBuffer.tabLabel()); - final var tabLabel = new Label(fileBuffer.tabLabel()); - final var dirtyIndicator = new StackPane(); - final var closeChip = new StackPane(); - final var closeIcon = new SVGPath(); - final var tabContent = new HBox(); - tabButton.setFocusTraversable(false); - tabButton.getStyleClass().addAll( - "studio-button", - "studio-button-secondary", - "editor-workspace-tab-button"); - tabButton.getStyleClass().add( - fileBuffer.readOnly() - ? "editor-workspace-tab-button-read-only" - : "editor-workspace-tab-button-editable"); - tabLabel.getStyleClass().add("editor-workspace-tab-label"); - tabLabel.setTextOverrun(OverrunStyle.ELLIPSIS); - dirtyIndicator.getStyleClass().add("editor-workspace-tab-dirty-indicator"); - closeChip.getStyleClass().add("editor-workspace-tab-close-chip"); - closeIcon.setContent("M 3 3 L 9 9 M 9 3 L 3 9"); - closeIcon.getStyleClass().add("editor-workspace-tab-close-icon"); - closeIcon.setMouseTransparent(true); - closeChip.getChildren().add(closeIcon); - tabContent.getStyleClass().add("editor-workspace-tab-content"); - tabContent.setAlignment(Pos.CENTER_LEFT); - HBox.setHgrow(tabLabel, Priority.ALWAYS); - dirtyIndicator.setManaged(fileBuffer.dirty()); - dirtyIndicator.setVisible(fileBuffer.dirty()); - tabContent.getChildren().addAll(tabLabel, dirtyIndicator, closeChip); - tabButton.setText(null); - tabButton.setGraphic(tabContent); - applyTabMetrics(tabButton, tabLabel, dirtyIndicator, closeChip); - if (fileBuffer.path().equals(activePath)) { - tabButton.getStyleClass().add("editor-workspace-tab-button-active"); - } - tabButton.setOnAction(event -> tabSelectionAction.accept(fileBuffer.path())); - configureCloseChip(closeChip, fileBuffer.path()); - getChildren().add(tabButton); - } - - getChildren().add(spacer); - final boolean hasOverflow = openFiles.size() > visibleCount; - overflowButton.getItems().setAll(buildOverflowItems(startIndex, endIndex)); - overflowButton.setVisible(hasOverflow); - overflowButton.setManaged(hasOverflow); - overflowButton.setDisable(!hasOverflow); - getChildren().add(overflowButton); - } - - private List buildOverflowItems(final int startIndex, final int endIndex) { - final var items = new ArrayList(); - for (int index = 0; index < openFiles.size(); index++) { - if (index >= startIndex && index < endIndex) { - continue; - } - final var fileBuffer = openFiles.get(index); - final var label = new Label(fileBuffer.tabLabel()); - label.getStyleClass().add("editor-workspace-tab-overflow-item"); - label.setMinWidth(OVERFLOW_MENU_WIDTH_HINT); - label.setPrefWidth(OVERFLOW_MENU_WIDTH_HINT); - label.setMaxWidth(OVERFLOW_MENU_WIDTH_HINT); - label.setMinHeight(TAB_HEIGHT_HINT); - label.setPrefHeight(TAB_HEIGHT_HINT); - label.setMaxHeight(TAB_HEIGHT_HINT); - label.setAlignment(Pos.CENTER_LEFT); - label.setTextOverrun(OverrunStyle.ELLIPSIS); - - final var item = new CustomMenuItem(label, true); - item.getStyleClass().add("editor-workspace-tab-overflow-menu-item"); - item.setOnAction(event -> tabSelectionAction.accept(fileBuffer.path())); - items.add(item); - } - return items; - } - - private int activeIndex() { - if (activePath == null) { - return Math.max(0, openFiles.size() - 1); - } - for (int index = 0; index < openFiles.size(); index++) { - if (openFiles.get(index).path().equals(activePath)) { - return index; - } - } - return Math.max(0, openFiles.size() - 1); - } - - private int visibleCount() { - final double availableWidth = getWidth() > 0 ? getWidth() : 760; - final double usableWidth = Math.max(availableWidth - OVERFLOW_WIDTH_HINT, TAB_WIDTH_HINT); - return Math.max(1, (int) Math.floor(usableWidth / TAB_WIDTH_HINT)); - } - - private void applyTabMetrics( - final Button button, - final Label tabLabel, - final StackPane dirtyIndicator, - final StackPane closeChip) { - button.setMinWidth(TAB_WIDTH_HINT); - button.setPrefWidth(TAB_WIDTH_HINT); - button.setMaxWidth(TAB_WIDTH_HINT); - button.setMinHeight(TAB_HEIGHT_HINT); - button.setPrefHeight(TAB_HEIGHT_HINT); - button.setMaxHeight(TAB_HEIGHT_HINT); - button.setMnemonicParsing(false); - tabLabel.setMinWidth(0); - tabLabel.setPrefWidth(TAB_WIDTH_HINT - 30); - tabLabel.setMaxWidth(Double.MAX_VALUE); - dirtyIndicator.setMinWidth(8); - dirtyIndicator.setPrefWidth(8); - dirtyIndicator.setMaxWidth(8); - dirtyIndicator.setMinHeight(8); - dirtyIndicator.setPrefHeight(8); - dirtyIndicator.setMaxHeight(8); - closeChip.setMinWidth(14); - closeChip.setPrefWidth(14); - closeChip.setMaxWidth(14); - closeChip.setMinHeight(14); - closeChip.setPrefHeight(14); - closeChip.setMaxHeight(14); - } - - private void applyOverflowMetrics() { - overflowButton.setMinWidth(OVERFLOW_WIDTH_HINT); - overflowButton.setPrefWidth(OVERFLOW_WIDTH_HINT); - overflowButton.setMaxWidth(OVERFLOW_WIDTH_HINT); - overflowButton.setMinHeight(TAB_HEIGHT_HINT); - overflowButton.setPrefHeight(TAB_HEIGHT_HINT); - overflowButton.setMaxHeight(TAB_HEIGHT_HINT); - overflowButton.setMnemonicParsing(false); - } - - private void configureCloseChip(final StackPane closeChip, final Path filePath) { - closeChip.addEventFilter(MouseEvent.MOUSE_PRESSED, event -> { - event.consume(); - if (event.getButton() == MouseButton.PRIMARY && closeChip.contains(event.getX(), event.getY())) { - closeChip.pseudoClassStateChanged(PRESSED_PSEUDO_CLASS, true); - } - }); - closeChip.addEventFilter(MouseEvent.MOUSE_DRAGGED, event -> { - event.consume(); - closeChip.pseudoClassStateChanged( - PRESSED_PSEUDO_CLASS, - event.isPrimaryButtonDown() && closeChip.contains(event.getX(), event.getY())); - }); - closeChip.addEventFilter(MouseEvent.MOUSE_RELEASED, event -> { - event.consume(); - final boolean shouldClose = event.getButton() == MouseButton.PRIMARY - && closeChip.getPseudoClassStates().contains(PRESSED_PSEUDO_CLASS) - && closeChip.contains(event.getX(), event.getY()); - closeChip.pseudoClassStateChanged(PRESSED_PSEUDO_CLASS, false); - if (shouldClose) { - tabCloseAction.accept(filePath); - } - }); - closeChip.addEventFilter(MouseEvent.MOUSE_EXITED, event -> - closeChip.pseudoClassStateChanged(PRESSED_PSEUDO_CLASS, false)); - } -} diff --git a/prometeu-studio/src/main/java/p/studio/workspaces/editor/EditorWarningStrip.java b/prometeu-studio/src/main/java/p/studio/workspaces/editor/EditorWarningStrip.java deleted file mode 100644 index 615c205c..00000000 --- a/prometeu-studio/src/main/java/p/studio/workspaces/editor/EditorWarningStrip.java +++ /dev/null @@ -1,103 +0,0 @@ -package p.studio.workspaces.editor; - -import javafx.geometry.Pos; -import javafx.scene.control.Button; -import javafx.scene.control.Label; -import javafx.scene.layout.HBox; -import javafx.scene.layout.Priority; -import javafx.scene.layout.Region; - -import java.util.List; -import java.util.Objects; - -public final class EditorWarningStrip extends HBox { - private final Label message = new Label(); - private final Label counter = new Label(); - private final Button previousButton = new Button("‹"); - private final Button nextButton = new Button("›"); - private final Button closeButton = new Button("×"); - - private List warnings = List.of(); - private int activeIndex; - private boolean dismissed; - - public EditorWarningStrip() { - setAlignment(Pos.CENTER_LEFT); - getStyleClass().add("editor-workspace-warning"); - - message.setWrapText(true); - message.setMaxWidth(Double.MAX_VALUE); - HBox.setHgrow(message, Priority.ALWAYS); - - counter.getStyleClass().add("editor-workspace-warning-counter"); - - previousButton.getStyleClass().add("editor-workspace-warning-button"); - nextButton.getStyleClass().add("editor-workspace-warning-button"); - closeButton.getStyleClass().add("editor-workspace-warning-button"); - - previousButton.setFocusTraversable(false); - nextButton.setFocusTraversable(false); - closeButton.setFocusTraversable(false); - - previousButton.setOnAction(event -> showIndex(activeIndex - 1)); - nextButton.setOnAction(event -> showIndex(activeIndex + 1)); - closeButton.setOnAction(event -> dismiss()); - - final var spacer = new Region(); - HBox.setHgrow(spacer, Priority.ALWAYS); - getChildren().addAll(message, spacer, counter, previousButton, nextButton, closeButton); - setVisible(false); - setManaged(false); - } - - public void showWarnings(final List warningItems) { - warnings = List.copyOf(Objects.requireNonNull(warningItems, "warningItems")); - activeIndex = 0; - dismissed = false; - refresh(); - } - - public void clearWarnings() { - warnings = List.of(); - activeIndex = 0; - dismissed = false; - refresh(); - } - - private void dismiss() { - dismissed = true; - refresh(); - } - - private void showIndex(final int candidateIndex) { - if (warnings.isEmpty()) { - return; - } - activeIndex = Math.floorMod(candidateIndex, warnings.size()); - refresh(); - } - - private void refresh() { - final boolean visible = !dismissed && !warnings.isEmpty(); - setVisible(visible); - setManaged(visible); - if (!visible) { - message.setText(""); - counter.setText(""); - return; - } - - final WarningItem warning = warnings.get(activeIndex); - message.setText(warning.message()); - counter.setText(warnings.size() == 1 ? "1/1" : (activeIndex + 1) + "/" + warnings.size()); - final boolean canNavigate = warnings.size() > 1; - previousButton.setDisable(!canNavigate); - nextButton.setDisable(!canNavigate); - } - - public record WarningItem(String message) { - public WarningItem { - message = Objects.requireNonNull(message, "message"); - } - } -} diff --git a/prometeu-studio/src/main/java/p/studio/workspaces/editor/EditorWorkspace.java b/prometeu-studio/src/main/java/p/studio/workspaces/editor/EditorWorkspace.java deleted file mode 100644 index cf9d3cc7..00000000 --- a/prometeu-studio/src/main/java/p/studio/workspaces/editor/EditorWorkspace.java +++ /dev/null @@ -1,784 +0,0 @@ -package p.studio.workspaces.editor; - -import javafx.application.Platform; -import javafx.scene.Node; -import javafx.scene.control.Alert; -import javafx.scene.control.Button; -import javafx.scene.control.ButtonBar; -import javafx.scene.control.ButtonType; -import javafx.scene.input.KeyCode; -import javafx.scene.input.KeyCodeCombination; -import javafx.scene.input.KeyCombination; -import javafx.scene.input.KeyEvent; -import javafx.scene.control.SplitPane; -import javafx.scene.layout.*; -import org.fxmisc.flowless.VirtualizedScrollPane; -import org.fxmisc.richtext.CodeArea; -import org.fxmisc.richtext.LineNumberFactory; -import org.reactfx.Subscription; -import p.studio.lsp.LspService; -import p.studio.lsp.messages.LspAnalyzeDocumentRequest; -import p.studio.lsp.messages.LspAnalyzeDocumentResult; -import p.studio.projectstate.ProjectLocalStudioSetup; -import p.studio.projectstate.ProjectLocalStudioState; -import p.studio.projects.ProjectReference; -import p.studio.utilities.i18n.I18n; -import p.studio.vfs.VfsProjectDocument; -import p.studio.vfs.VfsDocumentOpenResult; -import p.studio.vfs.messages.VfsProjectNode; -import p.studio.workspaces.Workspace; -import p.studio.workspaces.WorkspaceId; - -import java.nio.file.Path; -import java.util.ArrayList; -import java.util.List; -import java.util.Objects; -import java.util.function.IntFunction; - -public final class EditorWorkspace extends Workspace { - private static final int CARET_SCROLL_CONTEXT_LINES = 2; - private static final KeyCombination SAVE_SHORTCUT = new KeyCodeCombination(KeyCode.S, KeyCombination.SHORTCUT_DOWN); - private static final KeyCombination SAVE_ALL_SHORTCUT = new KeyCodeCombination( - KeyCode.S, - KeyCombination.SHORTCUT_DOWN, - KeyCombination.SHIFT_DOWN); - private final BorderPane root = new BorderPane(); - private final CodeArea codeArea = new CodeArea(); - private final VirtualizedScrollPane codeScroller = new VirtualizedScrollPane<>(codeArea); - private final Button saveButton = new Button(); - private final Button saveAllButton = new Button(); - private final EditorWarningStrip warningStrip = new EditorWarningStrip(); - private final EditorProjectNavigatorPanel navigatorPanel = new EditorProjectNavigatorPanel(); - private final EditorOutlinePanel outlinePanel = new EditorOutlinePanel(); - private final EditorHelperPanel helperPanel = new EditorHelperPanel(); - private final EditorStatusBar statusBar = new EditorStatusBar(); - private final EditorTabStrip tabStrip = new EditorTabStrip(); - private final EditorDocumentPresentationRegistry presentationRegistry = new EditorDocumentPresentationRegistry(); - private final LspService prometeuLspService; - private final VfsProjectDocument vfsProjectDocument; - private final ProjectLocalStudioSetup.EditorIndentationSetup indentationSetup; - private final EditorOpenFileSession openFileSession = new EditorOpenFileSession(); - private final Subscription inlineHintChangeSubscription; - private final List activePresentationStylesheets = new ArrayList<>(); - private final IntFunction lineNumberFactory = LineNumberFactory.get(codeArea); - private EditorDocumentScopeGuideModel scopeGuideModel = EditorDocumentScopeGuideModel.empty(); - private EditorDocumentScopeGuideModel.ActiveGuides activeGuides = EditorDocumentScopeGuideModel.ActiveGuides.empty(); - private EditorInlineHintProjection inlineHintProjection = EditorInlineHintProjection.create( - "", - presentationRegistry.resolve("text").highlight(""), - List.of()); - private boolean syncingEditor; - private boolean applyingPendingLayoutState; - private int activeGuideParagraph = -1; - private boolean pendingCaretContextRestore; - private Runnable stateChangedAction = () -> { }; - private ProjectLocalStudioState.EditorLayoutState pendingEditorLayoutState = ProjectLocalStudioState.EditorLayoutState.defaults(); - private SplitPane contentSplit; - private SplitPane leftColumnSplit; - private SplitPane rightColumnSplit; - - public EditorWorkspace( - final ProjectReference projectReference, - final VfsProjectDocument vfsProjectDocument, - final LspService prometeuLspService, - final ProjectLocalStudioSetup.EditorIndentationSetup indentationSetup) { - super(projectReference); - this.vfsProjectDocument = Objects.requireNonNull(vfsProjectDocument, "vfsProjectDocument"); - this.prometeuLspService = Objects.requireNonNull(prometeuLspService, "prometeuLspService"); - this.indentationSetup = Objects.requireNonNull(indentationSetup, "indentationSetup"); - root.getStyleClass().add("editor-workspace"); - refreshParagraphGraphics(); - codeArea.setEditable(false); - codeArea.setWrapText(false); - codeArea.textProperty().addListener((ignored, previous, current) -> syncActiveDocumentToVfs(current)); - codeArea.caretPositionProperty().addListener((ignored, previous, current) -> { - final int caretOffset = current == null ? 0 : current.intValue(); - updateActiveGuides(caretOffset, codeArea.getCurrentParagraph()); - refreshStatusBarCaret(); - }); - codeArea.estimatedScrollYProperty().addListener((ignored, previous, current) -> - restoreCaretScrollContextIfNeeded(previous, current)); - codeArea.getStyleClass().add("editor-workspace-code-area"); - codeArea.addEventFilter(KeyEvent.KEY_PRESSED, this::guardInlineHintMutation); - codeArea.addEventFilter(KeyEvent.KEY_TYPED, this::guardInlineHintMutation); - root.addEventFilter(KeyEvent.KEY_PRESSED, this::handleWorkspaceShortcuts); - inlineHintChangeSubscription = codeArea.plainTextChanges().subscribe(change -> { - if (syncingEditor) { - return; - } - inlineHintProjection.applyDisplayChange( - change.getPosition(), - change.getRemoved().length(), - change.getInserted().length()); - }); - EditorDocumentPresentationStyles.applyToCodeArea(codeArea, presentationRegistry.resolve("text")); - configureCommandBar(); - configureWarning(); - showEditorPlaceholder(); - navigatorPanel.setRefreshAction(this::refreshNavigator); - navigatorPanel.setRevealActiveFileAction(this::revealActiveFileInNavigator); - navigatorPanel.setFileSelectionAction(this::openNode); - tabStrip.setTabSelectionAction(path -> { - openFileSession.activate(path); - notifyStateChanged(); - renderSession(); - }); - tabStrip.setTabCloseAction(this::requestCloseFile); - - root.setCenter(buildLayout()); - statusBar.showPlaceholder(presentationRegistry.resolve("text")); - } - - @Override public WorkspaceId workspaceId() { return WorkspaceId.EDITOR; } - @Override public I18n title() { return I18n.WORKSPACE_CODE; } - @Override public Node rootNode() { return root; } - - @Override - public void load() { - applyEditorLayoutState(pendingEditorLayoutState); - schedulePendingLayoutReapply(); - refreshNavigator(); - } - - @Override - public void unLoad() { - inlineHintChangeSubscription.unsubscribe(); - } - - public CodeArea codeArea() { return codeArea; } - - public void setStateChangedAction(final Runnable stateChangedAction) { - this.stateChangedAction = Objects.requireNonNull(stateChangedAction, "stateChangedAction"); - } - - public void restoreProjectLocalState(final ProjectLocalStudioState projectLocalStudioState) { - final ProjectLocalStudioState state = Objects.requireNonNull(projectLocalStudioState, "projectLocalStudioState"); - pendingEditorLayoutState = state.shellLayout().editorLayout(); - reapplyPendingLayoutState(); - schedulePendingLayoutReapply(); - restoreEditorState(state.editorRestoration()); - } - - public void reapplyPendingLayoutState() { - applyEditorLayoutState(pendingEditorLayoutState); - } - - public ProjectLocalStudioState.EditorLayoutState captureLayoutState() { - return new ProjectLocalStudioState.EditorLayoutState( - dividerPositions(contentSplit), - dividerPositions(leftColumnSplit), - dividerPositions(rightColumnSplit), - dockPanelState(outlinePanel), - dockPanelState(helperPanel), - navigatorPanel.expandedPathStrings()); - } - - public ProjectLocalStudioState.EditorRestorationState captureRestorationState() { - return openFileSession.restorationState(); - } - - private void refreshNavigator() { - navigatorPanel.setSnapshot(vfsProjectDocument.refresh()); - } - - private void openNode(final VfsProjectNode node) { - final VfsDocumentOpenResult result = vfsProjectDocument.openDocument(node.path()); - if (result instanceof VfsDocumentOpenResult.VfsTextDocument textDocument) { - openFile(textDocument); - return; - } - showUnsupportedFileModal(node.path()); - } - - private void openFile(final VfsDocumentOpenResult.VfsTextDocument textDocument) { - openFileSession.open(bufferFrom(textDocument)); - notifyStateChanged(); - renderSession(); - } - - private void renderSession() { - final var activeFile = openFileSession.activeFile(); - navigatorPanel.setRevealActiveFileAvailable(activeFile.isPresent()); - tabStrip.showOpenFiles( - openFileSession.openFiles(), - activeFile.map(EditorOpenFileBuffer::path).orElse(null)); - if (activeFile.isEmpty()) { - showEditorPlaceholder(); - final EditorDocumentPresentation presentation = presentationRegistry.resolve("text"); - applyPresentationStylesheets(presentation); - EditorDocumentPresentationStyles.applyToCodeArea(codeArea, presentation); - statusBar.showPlaceholder(presentation); - outlinePanel.showPlaceholder(); - return; - } - - final var fileBuffer = activeFile.orElseThrow(); - final LspAnalyzeDocumentResult analysis = fileBuffer.frontendDocument() - ? prometeuLspService.analyzeDocument(new LspAnalyzeDocumentRequest(fileBuffer.path())) - : null; - final EditorDocumentPresentation presentation = presentationRegistry.resolve( - fileBuffer.typeId(), - analysis == null ? null : analysis.semanticPresentation()); - final EditorDocumentHighlightingResult highlighting = EditorDocumentHighlightingRouter.route( - fileBuffer, - presentation, - analysis); - scopeGuideModel = guidesFor(fileBuffer, analysis); - applyPresentationStylesheets(presentation); - syncingEditor = true; - try { - inlineHintProjection = EditorInlineHintProjection.create( - fileBuffer.content(), - highlighting.styleSpans(), - highlighting.inlineHints()); - codeArea.replaceText(inlineHintProjection.displayText()); - codeArea.setStyleSpans(0, inlineHintProjection.displayStyles()); - codeArea.moveTo(0); - } finally { - syncingEditor = false; - } - activeGuides = scopeGuideModel.resolveActiveGuides(codeArea.getCaretPosition()); - activeGuideParagraph = codeArea.getCurrentParagraph(); - refreshParagraphGraphics(); - Platform.runLater(() -> { - if (fileBuffer.editable()) { - codeArea.requestFocus(); - } - }); - codeArea.setEditable(fileBuffer.editable()); - EditorDocumentPresentationStyles.applyToCodeArea(codeArea, presentation); - refreshCommandSurfaces(fileBuffer); - statusBar.showFile(projectReference, fileBuffer, presentation, indentationSetup.statusLabel()); - refreshStatusBarCaret(); - refreshSemanticOutline(fileBuffer, analysis); - } - - private void revealActiveFileInNavigator() { - openFileSession.activeFile() - .map(EditorOpenFileBuffer::path) - .ifPresent(navigatorPanel::revealPath); - } - - private void showUnsupportedFileModal(final Path path) { - final var alert = new Alert(Alert.AlertType.INFORMATION); - if (root.getScene() != null) { - alert.initOwner(root.getScene().getWindow()); - } - alert.setHeaderText(null); - alert.setTitle(p.studio.Container.i18n().text(I18n.CODE_EDITOR_UNSUPPORTED_FILE_TITLE)); - alert.setContentText(p.studio.Container.i18n().format(I18n.CODE_EDITOR_UNSUPPORTED_FILE_MESSAGE, path.getFileName())); - alert.showAndWait(); - } - - private void showEditorPlaceholder() { - final EditorDocumentPresentation presentation = presentationRegistry.resolve("text"); - scopeGuideModel = EditorDocumentScopeGuideModel.empty(); - activeGuides = EditorDocumentScopeGuideModel.ActiveGuides.empty(); - activeGuideParagraph = -1; - refreshParagraphGraphics(); - applyPresentationStylesheets(presentation); - syncingEditor = true; - try { - inlineHintProjection = EditorInlineHintProjection.create("", presentation.highlight(""), List.of()); - codeArea.replaceText(""); - codeArea.setStyleSpans(0, inlineHintProjection.displayStyles()); - codeArea.moveTo(0); - } finally { - syncingEditor = false; - } - codeArea.setEditable(false); - EditorDocumentPresentationStyles.applyToCodeArea(codeArea, presentation); - saveButton.setDisable(true); - saveAllButton.setDisable(true); - warningStrip.clearWarnings(); - outlinePanel.showPlaceholder(); - helperPanel.showPlaceholder(); - } - - private void applyPresentationStylesheets(final EditorDocumentPresentation presentation) { - root.getStylesheets().removeAll(activePresentationStylesheets); - activePresentationStylesheets.clear(); - activePresentationStylesheets.addAll(presentation.stylesheetUrls()); - root.getStylesheets().addAll(activePresentationStylesheets); - } - - private void refreshParagraphGraphics() { - preserveViewport(() -> codeArea.setParagraphGraphicFactory(paragraphIndex -> EditorDocumentScopeGuideGraphicFactory.create( - lineNumberFactory.apply(paragraphIndex), - paragraphIndex, - scopeGuideModel, - activeGuides))); - } - - private VBox buildLayout() { - contentSplit = new SplitPane(buildLeftColumn(), buildRightColumn()); - contentSplit.setDividerPositions(0.30); - contentSplit.getStyleClass().add("editor-workspace-split"); - observeStatefulSplitPane(contentSplit); - - final var layout = new VBox(12, buildCommandBar(), contentSplit, statusBar); - layout.getStyleClass().add("editor-workspace-layout"); - VBox.setVgrow(contentSplit, Priority.ALWAYS); - return layout; - } - - private SplitPane buildLeftColumn() { - leftColumnSplit = outlinePanel.createBottomDockLayout(navigatorPanel, "editor-workspace-left-split"); - final var leftColumn = leftColumnSplit; - leftColumn.getStyleClass().add("editor-workspace-left-column"); - observeStatefulSplitPane(leftColumnSplit); - observeDockPane(outlinePanel); - return leftColumn; - } - - private VBox buildCenterColumn() { - final var editorViewport = new StackPane(codeScroller); - editorViewport.getStyleClass().add("editor-workspace-editor-viewport"); - final var editorSurface = new VBox(0, warningStrip, editorViewport); - editorSurface.getStyleClass().add("editor-workspace-editor-surface"); - codeScroller.getStyleClass().add("editor-workspace-code-scroller"); - VBox.setVgrow(editorViewport, Priority.ALWAYS); - final var centerColumn = new VBox(12, tabStrip, editorSurface); - centerColumn.getStyleClass().add("editor-workspace-center-column"); - VBox.setVgrow(editorSurface, Priority.ALWAYS); - return centerColumn; - } - - private SplitPane buildRightColumn() { - rightColumnSplit = helperPanel.createBottomDockLayout(buildCenterColumn(), "editor-workspace-right-split"); - observeStatefulSplitPane(rightColumnSplit); - observeDockPane(helperPanel); - return rightColumnSplit; - } - - private void configureCommandBar() { - saveButton.textProperty().bind(p.studio.Container.i18n().bind(I18n.CODE_EDITOR_COMMAND_SAVE)); - saveAllButton.textProperty().bind(p.studio.Container.i18n().bind(I18n.CODE_EDITOR_COMMAND_SAVE_ALL)); - saveButton.getStyleClass().addAll("studio-button", "studio-button-primary", "editor-workspace-command-button"); - saveAllButton.getStyleClass().addAll("studio-button", "studio-button-secondary", "editor-workspace-command-button"); - saveButton.setFocusTraversable(false); - saveAllButton.setFocusTraversable(false); - saveButton.setDisable(true); - saveAllButton.setDisable(true); - saveButton.setOnAction(event -> saveActiveFile()); - saveAllButton.setOnAction(event -> saveAllFiles()); - } - - private void configureWarning() { - warningStrip.clearWarnings(); - } - - private HBox buildCommandBar() { - final var spacer = new Region(); - HBox.setHgrow(spacer, Priority.ALWAYS); - final var commandBar = new HBox(8, saveButton, saveAllButton, spacer); - commandBar.getStyleClass().add("editor-workspace-command-bar"); - return commandBar; - } - - private void syncActiveDocumentToVfs(final String content) { - if (syncingEditor) { - return; - } - openFileSession.activeFile() - .filter(EditorOpenFileBuffer::editable) - .ifPresent(activeFile -> { - final String sourceContent = inlineHintProjection.stripDecorations(content); - final VfsDocumentOpenResult.VfsTextDocument updatedDocument = vfsProjectDocument.updateDocument(activeFile.path(), sourceContent); - openFileSession.open(bufferFrom(updatedDocument)); - pendingCaretContextRestore = true; - refreshEditableHighlighting(updatedDocument); - refreshEditableSemanticState(updatedDocument); - statusBar.showDocumentFormatting(updatedDocument.lineSeparator(), indentationSetup.statusLabel()); - tabStrip.showOpenFiles( - openFileSession.openFiles(), - openFileSession.activeFile().map(EditorOpenFileBuffer::path).orElse(null)); - refreshCommandSurfaces(openFileSession.activeFile().orElseThrow()); - }); - } - - private void refreshEditableHighlighting(final VfsDocumentOpenResult.VfsTextDocument updatedDocument) { - final EditorDocumentPresentation presentation = presentationRegistry.resolve(updatedDocument.typeId()); - inlineHintProjection = EditorInlineHintProjection.create( - updatedDocument.content(), - presentation.highlight(updatedDocument.content()), - List.of()); - preserveViewport(() -> codeArea.setStyleSpans(0, inlineHintProjection.displayStyles())); - } - - private void refreshEditableSemanticState(final VfsDocumentOpenResult.VfsTextDocument updatedDocument) { - final EditorOpenFileBuffer fileBuffer = openFileSession.activeFile().orElse(null); - if (fileBuffer == null || !fileBuffer.path().equals(updatedDocument.path())) { - return; - } - if (!updatedDocument.accessContext().frontendDocument()) { - scopeGuideModel = EditorDocumentScopeGuideModel.empty(); - activeGuides = EditorDocumentScopeGuideModel.ActiveGuides.empty(); - activeGuideParagraph = -1; - refreshParagraphGraphics(); - outlinePanel.showPlaceholder(); - helperPanel.showPlaceholder(); - return; - } - final LspAnalyzeDocumentResult analysis = prometeuLspService.analyzeDocument( - new LspAnalyzeDocumentRequest(updatedDocument.path())); - scopeGuideModel = guidesFor(fileBuffer, analysis); - activeGuides = scopeGuideModel.resolveActiveGuides(codeArea.getCaretPosition()); - activeGuideParagraph = codeArea.getCurrentParagraph(); - refreshParagraphGraphics(); - refreshSemanticOutline(fileBuffer, analysis); - } - - private void preserveViewport(final Runnable action) { - final int caretPosition = codeArea.getCaretPosition(); - final double scrollX = codeArea.estimatedScrollXProperty().getValue(); - final double scrollY = codeArea.estimatedScrollYProperty().getValue(); - action.run(); - codeArea.moveTo(Math.max(0, Math.min(caretPosition, codeArea.getLength()))); - Platform.runLater(() -> { - codeArea.scrollXToPixel(scrollX); - codeArea.scrollYToPixel(scrollY); - }); - } - - private void restoreCaretScrollContextIfNeeded(final Number previous, final Number current) { - if (!pendingCaretContextRestore) { - return; - } - final double previousValue = previous == null ? Double.NaN : previous.doubleValue(); - final double currentValue = current == null ? Double.NaN : current.doubleValue(); - if (!Double.isFinite(previousValue) || !Double.isFinite(currentValue) || Double.compare(previousValue, currentValue) == 0) { - return; - } - pendingCaretContextRestore = false; - Platform.runLater(() -> codeArea.showParagraphAtTop( - Math.max(0, codeArea.getCurrentParagraph() - CARET_SCROLL_CONTEXT_LINES))); - } - - private void saveActiveFile() { - openFileSession.activeFile() - .filter(EditorOpenFileBuffer::saveEnabled) - .ifPresent(activeFile -> { - vfsProjectDocument.saveDocument(activeFile.path()); - reloadOpenFilesFromVfs(activeFile.path()); - renderSession(); - }); - } - - private void saveAllFiles() { - if (!openFileSession.hasDirtyEditableFiles()) { - return; - } - vfsProjectDocument.saveAllDocuments(); - reloadOpenFilesFromVfs(openFileSession.activeFile().map(EditorOpenFileBuffer::path).orElse(null)); - renderSession(); - } - - private void requestCloseFile(final Path path) { - final var fileBuffer = openFileSession.file(path).orElse(null); - if (fileBuffer == null) { - return; - } - if (fileBuffer.dirty() && !confirmDirtyFileClose(fileBuffer)) { - return; - } - openFileSession.close(path); - notifyStateChanged(); - renderSession(); - } - - private boolean confirmDirtyFileClose(final EditorOpenFileBuffer fileBuffer) { - final var alert = new Alert(Alert.AlertType.CONFIRMATION); - if (root.getScene() != null) { - alert.initOwner(root.getScene().getWindow()); - } - final var saveButtonType = new ButtonType( - p.studio.Container.i18n().text(I18n.CODE_EDITOR_CLOSE_DIRTY_SAVE), - ButtonBar.ButtonData.YES); - final var discardButtonType = new ButtonType( - p.studio.Container.i18n().text(I18n.CODE_EDITOR_CLOSE_DIRTY_DISCARD), - ButtonBar.ButtonData.NO); - final var cancelButtonType = new ButtonType( - p.studio.Container.i18n().text(I18n.CODE_EDITOR_CLOSE_DIRTY_CANCEL), - ButtonBar.ButtonData.CANCEL_CLOSE); - alert.setTitle(p.studio.Container.i18n().text(I18n.CODE_EDITOR_CLOSE_DIRTY_TITLE)); - alert.setHeaderText(null); - alert.setContentText(p.studio.Container.i18n().format( - I18n.CODE_EDITOR_CLOSE_DIRTY_MESSAGE, - fileBuffer.tabLabel())); - alert.getButtonTypes().setAll(saveButtonType, discardButtonType, cancelButtonType); - final var result = alert.showAndWait().orElse(cancelButtonType); - if (result == saveButtonType) { - vfsProjectDocument.saveDocument(fileBuffer.path()); - return true; - } - if (result == discardButtonType) { - vfsProjectDocument.discardDocument(fileBuffer.path()); - return true; - } - return false; - } - - private void handleWorkspaceShortcuts(final KeyEvent event) { - if (SAVE_ALL_SHORTCUT.match(event)) { - if (!saveAllButton.isDisabled()) { - saveAllFiles(); - } - event.consume(); - return; - } - if (SAVE_SHORTCUT.match(event)) { - if (!saveButton.isDisabled()) { - saveActiveFile(); - } - event.consume(); - } - } - - private void reloadOpenFilesFromVfs(final Path activePath) { - final var openPaths = openFileSession.openFiles().stream() - .map(EditorOpenFileBuffer::path) - .toList(); - for (final var path : openPaths) { - final var result = vfsProjectDocument.openDocument(path); - if (result instanceof VfsDocumentOpenResult.VfsTextDocument textDocument) { - openFileSession.open(bufferFrom(textDocument)); - } - } - if (activePath != null) { - openFileSession.activate(activePath); - } - } - - private void refreshCommandSurfaces(final EditorOpenFileBuffer fileBuffer) { - saveButton.setDisable(!fileBuffer.saveEnabled()); - saveAllButton.setDisable(!openFileSession.hasDirtyEditableFiles()); - warningStrip.clearWarnings(); - } - - private EditorOpenFileBuffer bufferFrom(final VfsDocumentOpenResult.VfsTextDocument textDocument) { - return new EditorOpenFileBuffer( - textDocument.path(), - textDocument.documentName(), - textDocument.typeId(), - textDocument.content(), - textDocument.lineSeparator(), - textDocument.accessContext().frontendDocument(), - textDocument.accessContext().accessMode(), - textDocument.dirty()); - } - - private void refreshSemanticOutline( - final EditorOpenFileBuffer fileBuffer, - final LspAnalyzeDocumentResult analysis) { - if (!fileBuffer.frontendDocument() || analysis == null) { - outlinePanel.showPlaceholder(); - helperPanel.showPlaceholder(); - return; - } - outlinePanel.showSemanticReadResult(fileBuffer.path(), analysis.documentSymbols()); - helperPanel.showSemanticReadResult(fileBuffer.path(), analysis.diagnostics()); - } - - private EditorDocumentScopeGuideModel guidesFor( - final EditorOpenFileBuffer fileBuffer, - final LspAnalyzeDocumentResult analysis) { - if (!fileBuffer.frontendDocument() || analysis == null) { - return EditorDocumentScopeGuideModel.empty(); - } - if (!analysis.structuralAnchors().isEmpty()) { - return EditorDocumentScopeGuideModel.fromStructuralAnchors( - fileBuffer.content(), - analysis.structuralAnchors()); - } - return EditorDocumentScopeGuideModel.from(fileBuffer.content(), analysis.documentSymbols()); - } - - private void updateActiveGuides(final int caretOffset, final int currentParagraph) { - final EditorDocumentScopeGuideModel.ActiveGuides next = scopeGuideModel.resolveActiveGuides(caretOffset); - if (Objects.equals(activeGuides, next) && activeGuideParagraph == currentParagraph) { - return; - } - final boolean guidesChanged = !Objects.equals(activeGuides, next); - activeGuides = next; - final boolean paragraphChanged = activeGuideParagraph != currentParagraph; - activeGuideParagraph = currentParagraph; - if (!paragraphChanged && !guidesChanged) { - return; - } - refreshParagraphGraphics(); - } - - private void refreshStatusBarCaret() { - openFileSession.activeFile() - .filter(EditorOpenFileBuffer::editable) - .ifPresent(ignored -> statusBar.showCaretPosition( - codeArea.getCurrentParagraph() + 1, - codeArea.getCaretColumn() + 1)); - } - - private void guardInlineHintMutation(final KeyEvent event) { - if (syncingEditor || !codeArea.isEditable()) { - return; - } - final int selectionStart = codeArea.getSelection().getStart(); - final int selectionEnd = codeArea.getSelection().getEnd(); - if (selectionStart != selectionEnd && inlineHintProjection.touchesRange(selectionStart, selectionEnd)) { - event.consume(); - codeArea.moveTo(inlineHintProjection.clampCaret(selectionStart, false)); - return; - } - final int caret = codeArea.getCaretPosition(); - if (event.getEventType() == KeyEvent.KEY_TYPED) { - if (inlineHintProjection.containsOffset(caret)) { - event.consume(); - codeArea.moveTo(inlineHintProjection.clampCaret(caret, true)); - } - return; - } - if (event.getCode() == KeyCode.TAB) { - event.consume(); - codeArea.replaceSelection(indentationSetup.tabInsertion()); - return; - } - if (event.getCode() == KeyCode.BACK_SPACE && inlineHintProjection.containsOffset(Math.max(0, caret - 1))) { - event.consume(); - codeArea.moveTo(inlineHintProjection.clampCaret(Math.max(0, caret - 1), false)); - return; - } - if (event.getCode() == KeyCode.DELETE && inlineHintProjection.containsOffset(caret)) { - event.consume(); - codeArea.moveTo(inlineHintProjection.clampCaret(caret, true)); - } - } - - private void restoreEditorState(final ProjectLocalStudioState.EditorRestorationState editorRestorationState) { - openFileSession.clear(); - for (final String pathText : editorRestorationState.openTabPaths()) { - tryRestoreOpenFile(pathText); - } - if (editorRestorationState.activeTabPath() != null) { - try { - openFileSession.activate(Path.of(editorRestorationState.activeTabPath())); - } catch (RuntimeException ignored) { - // Fall back to the currently active restored tab. - } - } - renderSession(); - } - - private void tryRestoreOpenFile(final String pathText) { - try { - final Path path = Path.of(pathText).toAbsolutePath().normalize(); - final VfsDocumentOpenResult result = vfsProjectDocument.openDocument(path); - if (result instanceof VfsDocumentOpenResult.VfsTextDocument textDocument) { - openFileSession.open(bufferFrom(textDocument)); - } - } catch (RuntimeException ignored) { - // Invalid or unavailable persisted tabs are skipped and the editor falls back to the remaining state. - } - } - - private List dividerPositions(final SplitPane splitPane) { - if (splitPane == null || splitPane.getDividers().isEmpty()) { - return List.of(); - } - return splitPane.getDividers().stream() - .map(SplitPane.Divider::getPosition) - .toList(); - } - - private void applyDividerPositions(final SplitPane splitPane, final List positions) { - if (splitPane == null || positions == null || positions.isEmpty()) { - return; - } - final double[] values = positions.stream().mapToDouble(Double::doubleValue).toArray(); - splitPane.setDividerPositions(values); - } - - private ProjectLocalStudioState.DockPanelState dockPanelState(final p.studio.controls.WorkspaceDockPane dockPane) { - final p.studio.controls.WorkspaceDockPane.DockState state = dockPane.captureDockState(); - return new ProjectLocalStudioState.DockPanelState(state.expanded(), state.dividerPosition()); - } - - private void restoreDockPanelState( - final p.studio.controls.WorkspaceDockPane dockPane, - final ProjectLocalStudioState.DockPanelState dockPanelState) { - if (dockPanelState == null) { - return; - } - final double dividerPosition = dockPanelState.dividerPosition() == null - ? dockPane.captureDockState().dividerPosition() - : dockPanelState.dividerPosition(); - dockPane.restoreDockState(new p.studio.controls.WorkspaceDockPane.DockState( - dockPanelState.expanded(), - dividerPosition)); - } - - private void observeStatefulSplitPane(final SplitPane splitPane) { - splitPane.getDividers().forEach(divider -> - divider.positionProperty().addListener((ignored, previous, current) -> { - if (applyingPendingLayoutState) { - return; - } - notifyStateChanged(); - })); - splitPane.getDividers().addListener((javafx.collections.ListChangeListener) change -> { - while (change.next()) { - if (change.wasAdded()) { - change.getAddedSubList().forEach(divider -> - divider.positionProperty().addListener((ignored, previous, current) -> { - if (applyingPendingLayoutState) { - return; - } - notifyStateChanged(); - })); - } - } - }); - } - - private void observeDockPane(final p.studio.controls.WorkspaceDockPane dockPane) { - dockPane.expandedProperty().addListener((ignored, previous, current) -> { - if (applyingPendingLayoutState) { - return; - } - notifyStateChanged(); - }); - } - - private void notifyStateChanged() { - pendingEditorLayoutState = captureLayoutState(); - stateChangedAction.run(); - } - - private void schedulePendingLayoutReapply() { - if (contentSplit == null) { - return; - } - if (contentSplit.getWidth() > 0) { - Platform.runLater(this::reapplyPendingLayoutState); - return; - } - final javafx.beans.value.ChangeListener[] listenerRef = new javafx.beans.value.ChangeListener[1]; - listenerRef[0] = (ignored, previous, current) -> { - if (current == null || current.doubleValue() <= 0) { - return; - } - contentSplit.widthProperty().removeListener(listenerRef[0]); - Platform.runLater(this::reapplyPendingLayoutState); - }; - contentSplit.widthProperty().addListener(listenerRef[0]); - } - - private void applyEditorLayoutState(final ProjectLocalStudioState.EditorLayoutState editorLayoutState) { - applyingPendingLayoutState = true; - applyDividerPositions(contentSplit, editorLayoutState.contentSplitDividers()); - applyDividerPositions(leftColumnSplit, editorLayoutState.leftColumnDividers()); - applyDividerPositions(rightColumnSplit, editorLayoutState.rightColumnDividers()); - restoreDockPanelState(outlinePanel, editorLayoutState.outlinePanel()); - restoreDockPanelState(helperPanel, editorLayoutState.helperPanel()); - navigatorPanel.restoreExpandedPaths(editorLayoutState.navigatorExpandedPaths()); - Platform.runLater(() -> applyingPendingLayoutState = false); - } -} diff --git a/prometeu-studio/src/main/java/p/studio/workspaces/editor/EditorWorkspaceIcons.java b/prometeu-studio/src/main/java/p/studio/workspaces/editor/EditorWorkspaceIcons.java deleted file mode 100644 index 15d28072..00000000 --- a/prometeu-studio/src/main/java/p/studio/workspaces/editor/EditorWorkspaceIcons.java +++ /dev/null @@ -1,85 +0,0 @@ -package p.studio.workspaces.editor; - -import javafx.scene.Node; -import javafx.scene.layout.StackPane; -import javafx.scene.shape.SVGPath; - -import java.io.IOException; -import java.io.InputStream; -import java.nio.charset.StandardCharsets; -import java.util.regex.Matcher; -import java.util.regex.Pattern; - -public final class EditorWorkspaceIcons { - private static final Pattern SVG_PATH_PATTERN = Pattern.compile("]*\\sd=\"([^\"]+)\""); - private static final String FOLDER_PATH = "M1.5 4.5A1.5 1.5 0 0 1 3 3h3.2l1.1 1.4H13A1.5 1.5 0 0 1 14.5 5.9V12A1.5 1.5 0 0 1 13 13.5H3A1.5 1.5 0 0 1 1.5 12z"; - private static final String FILE_PATH = "M4 1.5h5l3 3V13A1.5 1.5 0 0 1 10.5 14.5h-6A1.5 1.5 0 0 1 3 13V3A1.5 1.5 0 0 1 4.5 1.5zm4.7 1.2V5h2.3z"; - private static final String COG_PATH = "M9.405 1.05c-.413-1.4-2.397-1.4-2.81 0l-.1.34a1.464 1.464 0 0 1-2.105.872l-.31-.17c-1.24-.68-2.64.72-1.96 1.96l.17.31c.446.816.023 1.84-.872 2.105l-.34.1c-1.4.413-1.4 2.397 0 2.81l.34.1c.895.265 1.318 1.289.872 2.105l-.17.31c-.68 1.24.72 2.64 1.96 1.96l.31-.17a1.464 1.464 0 0 1 2.105.872l.1.34c.413 1.4 2.397 1.4 2.81 0l.1-.34a1.464 1.464 0 0 1 2.105-.872l.31.17c1.24.68 2.64-.72 1.96-1.96l-.17-.31a1.464 1.464 0 0 1 .872-2.105l.34-.1c1.4-.413 1.4-2.397 0-2.81l-.34-.1a1.464 1.464 0 0 1-.872-2.105l.17-.31c.68-1.24-.72-2.64-1.96-1.96l-.31.17a1.464 1.464 0 0 1-2.105-.872z"; - private static final String REFRESH_PATH = "M8 2.2a5.8 5.8 0 0 1 4.3 1.9V2.8h1.2v3.8H9.7V5.4h1.8A4.6 4.6 0 1 0 12 11h1.3A5.9 5.9 0 1 1 8 2.2z"; - private static final String TARGET_PATH = "M7.25 1.5h1.5v1.9a4.85 4.85 0 0 1 3.85 3.85h1.9v1.5h-1.9a4.85 4.85 0 0 1-3.85 3.85v1.9h-1.5v-1.9A4.85 4.85 0 0 1 3.4 8.75H1.5v-1.5h1.9A4.85 4.85 0 0 1 7.25 3.4zm.75 3.25A3.25 3.25 0 1 0 8 11.25 3.25 3.25 0 0 0 8 4.75zm0 1.65a1.6 1.6 0 1 1 0 3.2 1.6 1.6 0 0 1 0-3.2z"; - - private EditorWorkspaceIcons() { - } - - public static Node folderDefault() { - return icon(FOLDER_PATH, "editor-workspace-icon-folder-default"); - } - - public static Node folderSource() { - return icon(FOLDER_PATH, "editor-workspace-icon-folder-source"); - } - - public static Node folderBuild() { - return icon(FOLDER_PATH, "editor-workspace-icon-folder-build"); - } - - public static Node file() { - return icon(FILE_PATH, "editor-workspace-icon-file"); - } - - public static Node cog() { - return icon(COG_PATH, "editor-workspace-icon-cog"); - } - - public static Node refresh() { - return icon(REFRESH_PATH, "editor-workspace-icon-refresh"); - } - - public static Node target() { - return icon(TARGET_PATH, "editor-workspace-icon-target"); - } - - public static Node lockClosed() { - return icon(iconPathFromResource("/icons/editor/lock-closed.svg"), "editor-workspace-icon-lock-closed"); - } - - public static Node lockOpen() { - return icon(iconPathFromResource("/icons/editor/lock-open.svg"), "editor-workspace-icon-lock-open"); - } - - private static Node icon(final String path, final String toneClass) { - final var shape = new SVGPath(); - shape.setContent(path); - shape.getStyleClass().addAll("editor-workspace-icon-shape", toneClass); - - final var icon = new StackPane(shape); - icon.getStyleClass().add("editor-workspace-icon"); - return icon; - } - - private static String iconPathFromResource(final String resourcePath) { - try (InputStream inputStream = EditorWorkspaceIcons.class.getResourceAsStream(resourcePath)) { - if (inputStream == null) { - throw new IllegalStateException("Missing icon resource: " + resourcePath); - } - final String svg = new String(inputStream.readAllBytes(), StandardCharsets.UTF_8); - final Matcher matcher = SVG_PATH_PATTERN.matcher(svg); - if (!matcher.find()) { - throw new IllegalStateException("Missing in icon resource: " + resourcePath); - } - return matcher.group(1); - } catch (IOException exception) { - throw new IllegalStateException("Unable to read icon resource: " + resourcePath, exception); - } - } -} diff --git a/prometeu-studio/src/main/java/p/studio/workspaces/editor/syntaxhighlight/EditorDocumentHighlightToken.java b/prometeu-studio/src/main/java/p/studio/workspaces/editor/syntaxhighlight/EditorDocumentHighlightToken.java deleted file mode 100644 index fc1c8c9d..00000000 --- a/prometeu-studio/src/main/java/p/studio/workspaces/editor/syntaxhighlight/EditorDocumentHighlightToken.java +++ /dev/null @@ -1,25 +0,0 @@ -package p.studio.workspaces.editor.syntaxhighlight; - -import java.util.Collection; -import java.util.List; -import java.util.Objects; - -public record EditorDocumentHighlightToken( - String groupName, - Collection styleClasses) { - - public EditorDocumentHighlightToken(final String groupName, final String styleClass) { - this(groupName, List.of(styleClass)); - } - - public EditorDocumentHighlightToken { - groupName = Objects.requireNonNull(groupName, "groupName"); - styleClasses = List.copyOf(Objects.requireNonNull(styleClasses, "styleClasses")); - if (groupName.isBlank()) { - throw new IllegalArgumentException("groupName cannot be blank"); - } - if (styleClasses.isEmpty()) { - throw new IllegalArgumentException("styleClasses cannot be empty"); - } - } -} \ No newline at end of file diff --git a/prometeu-studio/src/main/java/p/studio/workspaces/editor/syntaxhighlight/EditorDocumentSemanticHighlighting.java b/prometeu-studio/src/main/java/p/studio/workspaces/editor/syntaxhighlight/EditorDocumentSemanticHighlighting.java deleted file mode 100644 index 89dd1487..00000000 --- a/prometeu-studio/src/main/java/p/studio/workspaces/editor/syntaxhighlight/EditorDocumentSemanticHighlighting.java +++ /dev/null @@ -1,64 +0,0 @@ -package p.studio.workspaces.editor.syntaxhighlight; - -import org.fxmisc.richtext.model.StyleSpans; -import org.fxmisc.richtext.model.StyleSpansBuilder; -import p.studio.lsp.dtos.LspHighlightSpanDTO; - -import java.util.Collection; -import java.util.Collections; -import java.util.Comparator; -import java.util.LinkedHashSet; -import java.util.List; - -public final class EditorDocumentSemanticHighlighting { - private EditorDocumentSemanticHighlighting() { - } - - public static StyleSpans> highlight( - final String content, - final List semanticHighlights) { - final StyleSpansBuilder> builder = new StyleSpansBuilder<>(); - final List orderedHighlights = semanticHighlights.stream() - .sorted(Comparator.comparingInt(highlight -> highlight.range().startOffset())) - .toList(); - int cursor = 0; - for (final LspHighlightSpanDTO highlight : orderedHighlights) { - final int start = Math.max(cursor, highlight.range().startOffset()); - final int end = Math.min(content.length(), highlight.range().endOffset()); - if (start > cursor) { - builder.add(Collections.emptyList(), start - cursor); - } - if (end > start) { - builder.add(List.of("editor-semantic-" + highlight.semanticKey()), end - start); - cursor = end; - } - } - if (cursor < content.length()) { - builder.add(Collections.emptyList(), content.length() - cursor); - } - if (content.isEmpty()) { - builder.add(Collections.emptyList(), 0); - } - return builder.create(); - } - - public static StyleSpans> overlay( - final StyleSpans> baseHighlighting, - final StyleSpans> semanticHighlighting) { - return baseHighlighting.overlay(semanticHighlighting, EditorDocumentSemanticHighlighting::mergeStyles); - } - - private static Collection mergeStyles( - final Collection baseStyles, - final Collection semanticStyles) { - if (baseStyles.isEmpty()) { - return semanticStyles; - } - if (semanticStyles.isEmpty()) { - return baseStyles; - } - final LinkedHashSet merged = new LinkedHashSet<>(baseStyles); - merged.addAll(semanticStyles); - return List.copyOf(merged); - } -} diff --git a/prometeu-studio/src/main/java/p/studio/workspaces/editor/syntaxhighlight/EditorDocumentSyntaxHighlighting.java b/prometeu-studio/src/main/java/p/studio/workspaces/editor/syntaxhighlight/EditorDocumentSyntaxHighlighting.java deleted file mode 100644 index 92271b9b..00000000 --- a/prometeu-studio/src/main/java/p/studio/workspaces/editor/syntaxhighlight/EditorDocumentSyntaxHighlighting.java +++ /dev/null @@ -1,59 +0,0 @@ -package p.studio.workspaces.editor.syntaxhighlight; - -import org.fxmisc.richtext.model.StyleSpans; -import org.fxmisc.richtext.model.StyleSpansBuilder; - -import java.util.Collection; -import java.util.Collections; -import java.util.List; -import java.util.Objects; -import java.util.regex.Matcher; -import java.util.regex.Pattern; - -public record EditorDocumentSyntaxHighlighting( - Pattern tokenPattern, - List tokens) { - - public EditorDocumentSyntaxHighlighting { - tokens = List.copyOf(Objects.requireNonNull(tokens, "tokens")); - if (tokenPattern == null && !tokens.isEmpty()) { - throw new IllegalArgumentException("plain text highlighting cannot define tokens"); - } - if (tokenPattern != null && tokens.isEmpty()) { - throw new IllegalArgumentException("token-based highlighting requires tokens"); - } - } - - public static EditorDocumentSyntaxHighlighting plainText() { return EditorDocumentSyntaxHighlightingPlainText.PLAIN_TEXT; } - public static EditorDocumentSyntaxHighlighting json() { return EditorDocumentSyntaxHighlightingJson.JSON; } - public static EditorDocumentSyntaxHighlighting bash() { return EditorDocumentSyntaxHighlightingBash.BASH; } - - public StyleSpans> highlight(final String content) { - final StyleSpansBuilder> builder = new StyleSpansBuilder<>(); - if (tokenPattern == null) { - builder.add(Collections.emptyList(), content.length()); - return builder.create(); - } - - final Matcher matcher = tokenPattern.matcher(content); - int lastMatchEnd = 0; - - while (matcher.find()) { - builder.add(Collections.emptyList(), matcher.start() - lastMatchEnd); - builder.add(styleClassFor(matcher), matcher.end() - matcher.start()); - lastMatchEnd = matcher.end(); - } - - builder.add(Collections.emptyList(), content.length() - lastMatchEnd); - return builder.create(); - } - - private Collection styleClassFor(final Matcher matcher) { - for (final EditorDocumentHighlightToken token : tokens) { - if (matcher.group(token.groupName()) != null) { - return token.styleClasses(); - } - } - throw new IllegalStateException("matched token without registered style"); - } -} diff --git a/prometeu-studio/src/main/java/p/studio/workspaces/editor/syntaxhighlight/EditorDocumentSyntaxHighlightingBash.java b/prometeu-studio/src/main/java/p/studio/workspaces/editor/syntaxhighlight/EditorDocumentSyntaxHighlightingBash.java deleted file mode 100644 index 3623b37e..00000000 --- a/prometeu-studio/src/main/java/p/studio/workspaces/editor/syntaxhighlight/EditorDocumentSyntaxHighlightingBash.java +++ /dev/null @@ -1,28 +0,0 @@ -package p.studio.workspaces.editor.syntaxhighlight; - -import java.util.List; -import java.util.regex.Pattern; - -public class EditorDocumentSyntaxHighlightingBash { - public static final EditorDocumentSyntaxHighlighting BASH = new EditorDocumentSyntaxHighlighting( - Pattern.compile( - "(?^#![^\\n]*)" - + "|(?(?m)(?\"(?:\\\\.|[^\"\\\\])*\"|'(?:\\\\.|[^'\\\\])*')" - + "|(?\\$\\{?[A-Za-z_][A-Za-z0-9_]*}?|\\$[0-9@*#?!$-])" - + "|(?(?m)^[ \\t]*test\\b)" - + "|(?(?m)^[ \\t]*[A-Za-z_./-][A-Za-z0-9_./-]*)" - + "|(?\\b(?:if|then|else|elif|fi|for|while|until|do|done|case|esac|in|function|select|time)\\b)" - + "|(?\\b(?:echo|printf|read|cd|pwd|export|local|readonly|unset|return|shift|source|trap|exit)\\b)" - + "|(?\\|\\||&&|;;|<<-?|>>|[|&;<>~=(){}\\[\\]])"), - List.of( - new EditorDocumentHighlightToken("SHEBANG", "editor-syntax-bash-shebang"), - new EditorDocumentHighlightToken("COMMENT", "editor-syntax-bash-comment"), - new EditorDocumentHighlightToken("STRING", "editor-syntax-bash-string"), - new EditorDocumentHighlightToken("VARIABLE", "editor-syntax-bash-variable"), - new EditorDocumentHighlightToken("TESTBUILTIN", "editor-syntax-bash-builtin"), - new EditorDocumentHighlightToken("KEYWORD", "editor-syntax-bash-keyword"), - new EditorDocumentHighlightToken("BUILTIN", "editor-syntax-bash-builtin"), - new EditorDocumentHighlightToken("COMMAND", "editor-syntax-bash-command"), - new EditorDocumentHighlightToken("OPERATOR", "editor-syntax-bash-operator"))); -} diff --git a/prometeu-studio/src/main/java/p/studio/workspaces/editor/syntaxhighlight/EditorDocumentSyntaxHighlightingJson.java b/prometeu-studio/src/main/java/p/studio/workspaces/editor/syntaxhighlight/EditorDocumentSyntaxHighlightingJson.java deleted file mode 100644 index 58f803e8..00000000 --- a/prometeu-studio/src/main/java/p/studio/workspaces/editor/syntaxhighlight/EditorDocumentSyntaxHighlightingJson.java +++ /dev/null @@ -1,22 +0,0 @@ -package p.studio.workspaces.editor.syntaxhighlight; - -import java.util.List; -import java.util.regex.Pattern; - -public class EditorDocumentSyntaxHighlightingJson { - public static final EditorDocumentSyntaxHighlighting JSON = new EditorDocumentSyntaxHighlighting( - Pattern.compile( - "(?\"(?:\\\\.|[^\"\\\\])*\"(?=\\s*:))" - + "|(?\"(?:\\\\.|[^\"\\\\])*\")" - + "|(?-?\\b\\d+(?:\\.\\d+)?(?:[eE][+-]?\\d+)?\\b)" - + "|(?\\b(?:true|false)\\b)" - + "|(?\\bnull\\b)" - + "|(?[\\{\\}\\[\\],:])"), - List.of( - new EditorDocumentHighlightToken("KEY", "editor-syntax-json-key"), - new EditorDocumentHighlightToken("STRING", "editor-syntax-json-string"), - new EditorDocumentHighlightToken("NUMBER", "editor-syntax-json-number"), - new EditorDocumentHighlightToken("BOOLEAN", "editor-syntax-json-boolean"), - new EditorDocumentHighlightToken("NULL", "editor-syntax-json-null"), - new EditorDocumentHighlightToken("PUNCTUATION", "editor-syntax-json-punctuation"))); -} diff --git a/prometeu-studio/src/main/java/p/studio/workspaces/editor/syntaxhighlight/EditorDocumentSyntaxHighlightingPlainText.java b/prometeu-studio/src/main/java/p/studio/workspaces/editor/syntaxhighlight/EditorDocumentSyntaxHighlightingPlainText.java deleted file mode 100644 index 1f13091b..00000000 --- a/prometeu-studio/src/main/java/p/studio/workspaces/editor/syntaxhighlight/EditorDocumentSyntaxHighlightingPlainText.java +++ /dev/null @@ -1,9 +0,0 @@ -package p.studio.workspaces.editor.syntaxhighlight; - -import java.util.List; - -public class EditorDocumentSyntaxHighlightingPlainText { - public static final EditorDocumentSyntaxHighlighting PLAIN_TEXT = new EditorDocumentSyntaxHighlighting( - null, - List.of()); -} diff --git a/prometeu-studio/src/test/java/p/studio/projectsessions/StudioProjectSessionFactoryTest.java b/prometeu-studio/src/test/java/p/studio/projectsessions/StudioProjectSessionFactoryTest.java index 42419295..62cf61f5 100644 --- a/prometeu-studio/src/test/java/p/studio/projectsessions/StudioProjectSessionFactoryTest.java +++ b/prometeu-studio/src/test/java/p/studio/projectsessions/StudioProjectSessionFactoryTest.java @@ -1,25 +1,11 @@ package p.studio.projectsessions; import org.junit.jupiter.api.Test; -import p.studio.lsp.messages.LspProjectContext; -import p.studio.lsp.LspService; -import p.studio.lsp.LspServiceFactory; import p.studio.projectstate.ProjectLocalStudioSetup; import p.studio.projectstate.ProjectLocalStudioSetupService; import p.studio.projectstate.ProjectLocalStudioState; import p.studio.projectstate.ProjectLocalStudioStateService; -import p.studio.lsp.dtos.LspSessionStateDTO; -import p.studio.lsp.messages.LspAnalyzeDocumentRequest; -import p.studio.lsp.messages.LspAnalyzeDocumentResult; -import p.studio.lsp.messages.LspDefinitionRequest; -import p.studio.lsp.messages.LspDefinitionResult; import p.studio.projects.ProjectReference; -import p.studio.vfs.VfsProjectDocument; -import p.studio.vfs.ProjectDocumentVfsFactory; -import p.studio.vfs.VfsDocumentOpenResult; -import p.studio.vfs.messages.VfsProjectContext; -import p.studio.vfs.messages.VfsProjectSnapshot; -import p.studio.vfs.messages.VfsRefreshRequest; import java.nio.file.Path; @@ -28,14 +14,10 @@ import static org.junit.jupiter.api.Assertions.assertSame; final class StudioProjectSessionFactoryTest { @Test - void openCreatesProjectSessionBackedByProjectScopedVfs() { - final RecordingLspFactory lspFactory = new RecordingLspFactory(); - final RecordingVfsFactory vfsFactory = new RecordingVfsFactory(); + void openCreatesProjectSessionWithoutLegacyEditorServices() { final RecordingProjectLocalStudioStateService stateService = new RecordingProjectLocalStudioStateService(); final RecordingProjectLocalStudioSetupService setupService = new RecordingProjectLocalStudioSetupService(); final StudioProjectSessionFactory sessionFactory = new StudioProjectSessionFactory( - lspFactory, - vfsFactory, stateService, setupService); final ProjectReference projectReference = new ProjectReference( @@ -48,14 +30,6 @@ final class StudioProjectSessionFactoryTest { final StudioProjectSession session = sessionFactory.open(projectReference); assertSame(projectReference, session.projectReference()); - assertSame(vfsFactory.vfs, session.projectDocumentVfs()); - assertSame(lspFactory.service, session.prometeuLspService()); - assertEquals("Example", vfsFactory.capturedContext.projectName()); - assertEquals("pbs", vfsFactory.capturedContext.languageId()); - assertEquals(projectReference.rootPath().toAbsolutePath().normalize(), vfsFactory.capturedContext.rootPath()); - assertEquals("Example", lspFactory.capturedContext.projectName()); - assertEquals("pbs", lspFactory.capturedContext.languageId()); - assertSame(vfsFactory.vfs, lspFactory.capturedVfs); assertSame(stateService.loadedState, session.projectLocalStudioState()); assertSame(setupService.loadedSetup, session.projectLocalStudioSetup()); assertEquals("IDLE", session.executionSession().snapshot().state().name()); @@ -68,8 +42,7 @@ final class StudioProjectSessionFactoryTest { private final ProjectLocalStudioState loadedState = new ProjectLocalStudioState( ProjectLocalStudioState.CURRENT_VERSION, ProjectLocalStudioState.ShellLayout.defaults(), - new ProjectLocalStudioState.OpenShellState("EDITOR"), - ProjectLocalStudioState.EditorRestorationState.defaults()); + new ProjectLocalStudioState.OpenShellState("ASSETS")); @Override public ProjectLocalStudioState load(final ProjectReference projectReference) { @@ -90,84 +63,4 @@ final class StudioProjectSessionFactoryTest { return loadedSetup; } } - - private static final class RecordingVfsFactory implements ProjectDocumentVfsFactory { - private VfsProjectContext capturedContext; - private final VfsProjectDocument vfs = new NoOpVfsProjectDocument(); - - @Override - public VfsProjectDocument open(VfsProjectContext projectContext) { - this.capturedContext = projectContext; - return vfs; - } - } - - private static final class RecordingLspFactory implements LspServiceFactory { - private LspProjectContext capturedContext; - private VfsProjectDocument capturedVfs; - private final LspService service = new NoOpPrometeuLspService(); - - @Override - public LspService open( - final LspProjectContext projectContext, - final VfsProjectDocument vfsProjectDocument) { - this.capturedContext = projectContext; - this.capturedVfs = vfsProjectDocument; - return service; - } - } - - private static final class NoOpVfsProjectDocument implements VfsProjectDocument { - @Override - public VfsProjectContext projectContext() { - throw new UnsupportedOperationException(); - } - - @Override - public VfsProjectSnapshot snapshot() { - throw new UnsupportedOperationException(); - } - - @Override - public VfsProjectSnapshot refresh() { - throw new UnsupportedOperationException(); - } - - @Override - public VfsProjectSnapshot refresh(VfsRefreshRequest request) { - throw new UnsupportedOperationException(); - } - - @Override - public VfsDocumentOpenResult openDocument(Path path) { - throw new UnsupportedOperationException(); - } - } - - private static final class NoOpPrometeuLspService implements LspService { - @Override - public LspProjectContext projectContext() { - throw new UnsupportedOperationException(); - } - - @Override - public VfsProjectDocument projectDocumentVfs() { - throw new UnsupportedOperationException(); - } - - @Override - public LspSessionStateDTO snapshot() { - throw new UnsupportedOperationException(); - } - - @Override - public LspAnalyzeDocumentResult analyzeDocument(final LspAnalyzeDocumentRequest request) { - throw new UnsupportedOperationException(); - } - - @Override - public LspDefinitionResult definition(final LspDefinitionRequest request) { - throw new UnsupportedOperationException(); - } - } } diff --git a/prometeu-studio/src/test/java/p/studio/projectsessions/StudioProjectSessionTest.java b/prometeu-studio/src/test/java/p/studio/projectsessions/StudioProjectSessionTest.java index 5b731bc8..87eca3bb 100644 --- a/prometeu-studio/src/test/java/p/studio/projectsessions/StudioProjectSessionTest.java +++ b/prometeu-studio/src/test/java/p/studio/projectsessions/StudioProjectSessionTest.java @@ -2,22 +2,10 @@ package p.studio.projectsessions; import org.junit.jupiter.api.Test; import p.studio.execution.StudioExecutionSessionService; -import p.studio.lsp.messages.LspProjectContext; -import p.studio.lsp.LspService; import p.studio.projectstate.ProjectLocalStudioSetup; import p.studio.projectstate.ProjectLocalStudioState; import p.studio.projectstate.ProjectLocalStudioStateService; -import p.studio.lsp.dtos.LspSessionStateDTO; -import p.studio.lsp.messages.LspAnalyzeDocumentRequest; -import p.studio.lsp.messages.LspAnalyzeDocumentResult; -import p.studio.lsp.messages.LspDefinitionRequest; -import p.studio.lsp.messages.LspDefinitionResult; import p.studio.projects.ProjectReference; -import p.studio.vfs.VfsProjectDocument; -import p.studio.vfs.VfsDocumentOpenResult; -import p.studio.vfs.messages.VfsProjectContext; -import p.studio.vfs.messages.VfsProjectSnapshot; -import p.studio.vfs.messages.VfsRefreshRequest; import java.nio.file.Path; @@ -26,14 +14,10 @@ import static org.junit.jupiter.api.Assertions.assertSame; final class StudioProjectSessionTest { @Test - void closeDelegatesToUnderlyingServicesOnlyOnce() { - final CountingVfsProjectDocument vfs = new CountingVfsProjectDocument(); - final CountingPrometeuLspService lsp = new CountingPrometeuLspService(vfs); + void closeSavesStateOnlyOnce() { final RecordingProjectLocalStudioStateService stateService = new RecordingProjectLocalStudioStateService(); final StudioProjectSession session = new StudioProjectSession( projectReference(), - lsp, - vfs, stateService, ProjectLocalStudioSetup.defaults(), new StudioExecutionSessionService(), @@ -42,27 +26,21 @@ final class StudioProjectSessionTest { session.close(); session.close(); - assertEquals(1, lsp.closeCalls); - assertEquals(1, vfs.closeCalls); assertEquals(1, stateService.saveCalls); assertEquals(projectReference(), stateService.savedProjectReference); } @Test void replaceProjectLocalStudioStateUpdatesTheSavedSnapshot() { - final CountingVfsProjectDocument vfs = new CountingVfsProjectDocument(); - final CountingPrometeuLspService lsp = new CountingPrometeuLspService(vfs); final RecordingProjectLocalStudioStateService stateService = new RecordingProjectLocalStudioStateService(); final StudioProjectSession session = new StudioProjectSession( projectReference(), - lsp, - vfs, stateService, ProjectLocalStudioSetup.defaults(), new StudioExecutionSessionService(), ProjectLocalStudioState.defaults()); final ProjectLocalStudioState nextState = ProjectLocalStudioState.defaults() - .withOpenShellState(new ProjectLocalStudioState.OpenShellState("EDITOR")); + .withOpenShellState(new ProjectLocalStudioState.OpenShellState("ASSETS")); session.replaceProjectLocalStudioState(nextState); session.close(); @@ -86,77 +64,4 @@ final class StudioProjectSessionTest { savedState = state; } } - - private static final class CountingVfsProjectDocument implements VfsProjectDocument { - private int closeCalls; - - @Override - public VfsProjectContext projectContext() { - throw new UnsupportedOperationException(); - } - - @Override - public VfsProjectSnapshot snapshot() { - throw new UnsupportedOperationException(); - } - - @Override - public VfsProjectSnapshot refresh() { - throw new UnsupportedOperationException(); - } - - @Override - public VfsProjectSnapshot refresh(VfsRefreshRequest request) { - throw new UnsupportedOperationException(); - } - - @Override - public VfsDocumentOpenResult openDocument(Path path) { - throw new UnsupportedOperationException(); - } - - @Override - public void close() { - closeCalls++; - } - } - - private static final class CountingPrometeuLspService implements LspService { - private final VfsProjectDocument vfsProjectDocument; - private int closeCalls; - - private CountingPrometeuLspService(final VfsProjectDocument vfsProjectDocument) { - this.vfsProjectDocument = vfsProjectDocument; - } - - @Override - public LspProjectContext projectContext() { - throw new UnsupportedOperationException(); - } - - @Override - public VfsProjectDocument projectDocumentVfs() { - return vfsProjectDocument; - } - - @Override - public LspSessionStateDTO snapshot() { - throw new UnsupportedOperationException(); - } - - @Override - public LspAnalyzeDocumentResult analyzeDocument(final LspAnalyzeDocumentRequest request) { - throw new UnsupportedOperationException(); - } - - @Override - public LspDefinitionResult definition(final LspDefinitionRequest request) { - throw new UnsupportedOperationException(); - } - - @Override - public void close() { - closeCalls++; - } - } } diff --git a/prometeu-studio/src/test/java/p/studio/projectstate/ProjectLocalStudioStateServiceTest.java b/prometeu-studio/src/test/java/p/studio/projectstate/ProjectLocalStudioStateServiceTest.java index 259b2f85..023b5d90 100644 --- a/prometeu-studio/src/test/java/p/studio/projectstate/ProjectLocalStudioStateServiceTest.java +++ b/prometeu-studio/src/test/java/p/studio/projectstate/ProjectLocalStudioStateServiceTest.java @@ -23,22 +23,8 @@ final class ProjectLocalStudioStateServiceTest { final ProjectLocalStudioState state = new ProjectLocalStudioState( ProjectLocalStudioState.CURRENT_VERSION, new ProjectLocalStudioState.ShellLayout( - new ProjectLocalStudioState.EditorLayoutState( - List.of(0.25d), - List.of(0.80d), - List.of(0.70d), - new ProjectLocalStudioState.DockPanelState(true, 0.80d), - new ProjectLocalStudioState.DockPanelState(false, 0.70d), - List.of( - project.rootPath().resolve("src").toString(), - project.rootPath().resolve("src/game").toString())), new ProjectLocalStudioState.AssetsLayoutState(List.of(0.42d))), - new ProjectLocalStudioState.OpenShellState("EDITOR"), - new ProjectLocalStudioState.EditorRestorationState( - List.of( - project.rootPath().resolve("src/main.pbs").toString(), - project.rootPath().resolve("README.md").toString()), - project.rootPath().resolve("src/main.pbs").toString())); + new ProjectLocalStudioState.OpenShellState("ASSETS")); service.save(project, state); @@ -72,6 +58,43 @@ final class ProjectLocalStudioStateServiceTest { assertEquals(ProjectLocalStudioState.defaults(), service.load(project)); } + @Test + void legacyEditorStateLoadsWithAssetsFallbackAndIgnoresEditorFields() throws Exception { + final ProjectLocalStudioStateService service = new ProjectLocalStudioStateService(); + final ProjectReference project = project("main"); + Files.createDirectories(ProjectStudioPaths.studioRoot(project)); + Files.writeString( + ProjectStudioPaths.statePath(project), + """ + { + "version": 1, + "shellLayout": { + "editorLayout": { + "contentSplitDividers": [0.2, 0.8] + }, + "assetsLayout": { + "contentSplitDividers": [0.42] + } + }, + "openShellState": { + "selectedWorkspaceId": "EDITOR" + }, + "editorRestoration": { + "openTabPaths": ["src/main.pbs"], + "activeTabPath": "src/main.pbs" + } + } + """); + + assertEquals( + new ProjectLocalStudioState( + ProjectLocalStudioState.CURRENT_VERSION, + new ProjectLocalStudioState.ShellLayout( + new ProjectLocalStudioState.AssetsLayoutState(List.of(0.42d))), + new ProjectLocalStudioState.OpenShellState("ASSETS")), + service.load(project)); + } + private ProjectReference project(final String name) { final Path projectRoot = tempDir.resolve(name); return new ProjectReference("Main", "1.0.0", "pbs", 1, projectRoot); diff --git a/prometeu-studio/src/test/java/p/studio/workspaces/editor/EditorDocumentHighlightingRouterTest.java b/prometeu-studio/src/test/java/p/studio/workspaces/editor/EditorDocumentHighlightingRouterTest.java deleted file mode 100644 index 26b9d405..00000000 --- a/prometeu-studio/src/test/java/p/studio/workspaces/editor/EditorDocumentHighlightingRouterTest.java +++ /dev/null @@ -1,315 +0,0 @@ -package p.studio.workspaces.editor; - -import org.junit.jupiter.api.Test; -import p.studio.lsp.dtos.LspHighlightSpanDTO; -import p.studio.lsp.dtos.LspSemanticPresentationDTO; -import p.studio.lsp.dtos.LspRangeDTO; -import p.studio.lsp.dtos.LspSessionStateDTO; -import p.studio.lsp.messages.LspAnalyzeDocumentResult; -import p.studio.vfs.messages.VfsDocumentAccessMode; - -import java.nio.file.Path; -import java.util.Collection; -import java.util.List; - -import static org.junit.jupiter.api.Assertions.assertEquals; -import static org.junit.jupiter.api.Assertions.assertFalse; -import static org.junit.jupiter.api.Assertions.assertTrue; - -final class EditorDocumentHighlightingRouterTest { - @Test - void frontendDocumentsUseLspOwnedHighlightsWhenSemanticSpansExist() { - final EditorDocumentPresentationRegistry registry = new EditorDocumentPresentationRegistry(); - final EditorOpenFileBuffer fileBuffer = new EditorOpenFileBuffer( - Path.of("/tmp/example/src/main.pbs"), - "main.pbs", - "pbs", - "fn main() -> void {}", - "LF", - true, - VfsDocumentAccessMode.READ_ONLY, - false); - - final LspAnalyzeDocumentResult analysis = new LspAnalyzeDocumentResult( - new LspSessionStateDTO(true, List.of("highlight")), - new LspSemanticPresentationDTO( - List.of("pbs-keyword", "pbs-function"), - List.of("/themes/pbs/semantic-highlighting.css")), - List.of(), - List.of( - new LspHighlightSpanDTO(new LspRangeDTO(0, 2), "pbs-keyword"), - new LspHighlightSpanDTO(new LspRangeDTO(3, 7), "pbs-function")), - List.of(), - List.of(), - List.of(), - List.of()); - - final EditorDocumentHighlightingResult result = EditorDocumentHighlightingRouter.route( - fileBuffer, - registry.resolve("pbs", analysis.semanticPresentation()), - analysis); - - assertEquals(EditorDocumentHighlightOwner.LSP, result.owner()); - assertTrue(result.inlineHints().isEmpty()); - assertTrue(containsStyle(result.styleSpans(), "editor-semantic-pbs-keyword")); - assertTrue(containsStyle(result.styleSpans(), "editor-semantic-pbs-function")); - } - - @Test - void nonFrontendDocumentsStayOnLocalHighlighting() { - final EditorDocumentPresentationRegistry registry = new EditorDocumentPresentationRegistry(); - final EditorOpenFileBuffer fileBuffer = new EditorOpenFileBuffer( - Path.of("/tmp/example/prometeu.json"), - "prometeu.json", - "json", - "{\n \"name\": \"Example\"\n}\n", - "LF", - false, - VfsDocumentAccessMode.EDITABLE, - false); - - final LspAnalyzeDocumentResult analysis = new LspAnalyzeDocumentResult( - new LspSessionStateDTO(true, List.of("highlight")), - new LspSemanticPresentationDTO(List.of(), List.of()), - List.of(), - List.of(new LspHighlightSpanDTO(new LspRangeDTO(0, 1), "fe-punctuation")), - List.of(), - List.of(), - List.of(), - List.of()); - - final EditorDocumentHighlightingResult result = EditorDocumentHighlightingRouter.route( - fileBuffer, - registry.resolve("json"), - analysis); - - assertEquals(EditorDocumentHighlightOwner.LOCAL, result.owner()); - assertTrue(result.inlineHints().isEmpty()); - } - - @Test - void frontendDocumentsFallbackToLocalPbsSyntaxWhenSemanticPresentationResourcesAreUnavailable() { - final EditorDocumentPresentationRegistry registry = new EditorDocumentPresentationRegistry(); - final EditorOpenFileBuffer fileBuffer = new EditorOpenFileBuffer( - Path.of("/tmp/example/src/main.pbs"), - "main.pbs", - "pbs", - "fn main() -> void {}", - "LF", - true, - VfsDocumentAccessMode.READ_ONLY, - false); - - final LspAnalyzeDocumentResult analysis = new LspAnalyzeDocumentResult( - new LspSessionStateDTO(true, List.of("highlight")), - new LspSemanticPresentationDTO( - List.of("pbs-keyword", "pbs-function"), - List.of("/themes/pbs/missing.css")), - List.of(), - List.of( - new LspHighlightSpanDTO(new LspRangeDTO(0, 2), "pbs-keyword"), - new LspHighlightSpanDTO(new LspRangeDTO(3, 7), "pbs-function")), - List.of(), - List.of(), - List.of(), - List.of()); - - final EditorDocumentHighlightingResult result = EditorDocumentHighlightingRouter.route( - fileBuffer, - registry.resolve("pbs", analysis.semanticPresentation()), - analysis); - - assertEquals(EditorDocumentHighlightOwner.LSP, result.owner()); - assertTrue(result.inlineHints().isEmpty()); - assertTrue(containsStyle(result.styleSpans(), "editor-semantic-pbs-keyword")); - assertTrue(containsStyle(result.styleSpans(), "editor-semantic-pbs-function")); - } - - @Test - void frontendServiceHighlightsProjectToDedicatedServiceCssClass() { - final EditorDocumentPresentationRegistry registry = new EditorDocumentPresentationRegistry(); - final EditorOpenFileBuffer fileBuffer = new EditorOpenFileBuffer( - Path.of("/tmp/example/src/main.pbs"), - "main.pbs", - "pbs", - "declare service Game {}", - "LF", - true, - VfsDocumentAccessMode.READ_ONLY, - false); - - final LspAnalyzeDocumentResult analysis = new LspAnalyzeDocumentResult( - new LspSessionStateDTO(true, List.of("highlight")), - new LspSemanticPresentationDTO( - List.of("pbs-service"), - List.of("/themes/pbs/semantic-highlighting.css")), - List.of(), - List.of(new LspHighlightSpanDTO(new LspRangeDTO(16, 20), "pbs-service")), - List.of(), - List.of(), - List.of(), - List.of()); - - final EditorDocumentHighlightingResult result = EditorDocumentHighlightingRouter.route( - fileBuffer, - registry.resolve("pbs", analysis.semanticPresentation()), - analysis); - - assertEquals(EditorDocumentHighlightOwner.LSP, result.owner()); - assertTrue(result.inlineHints().isEmpty()); - assertTrue(containsStyle(result.styleSpans(), "editor-semantic-pbs-service")); - } - - @Test - void frontendDocumentsKeepLocalSyntaxForRangesWithoutSemanticCoverage() { - final EditorDocumentPresentationRegistry registry = new EditorDocumentPresentationRegistry(); - final EditorOpenFileBuffer fileBuffer = new EditorOpenFileBuffer( - Path.of("/tmp/example/src/main.pbs"), - "main.pbs", - "pbs", - "fn main() -> void { Game.tick(1); }", - "LF", - true, - VfsDocumentAccessMode.READ_ONLY, - false); - - final LspAnalyzeDocumentResult analysis = new LspAnalyzeDocumentResult( - new LspSessionStateDTO(true, List.of("highlight")), - new LspSemanticPresentationDTO( - List.of("pbs-keyword", "pbs-service", "pbs-function"), - List.of("/themes/pbs/semantic-highlighting.css")), - List.of(), - List.of( - new LspHighlightSpanDTO(new LspRangeDTO(0, 2), "pbs-keyword"), - new LspHighlightSpanDTO(new LspRangeDTO(3, 7), "pbs-function"), - new LspHighlightSpanDTO(new LspRangeDTO(19, 23), "pbs-service")), - List.of(), - List.of(), - List.of(), - List.of()); - - final EditorDocumentHighlightingResult result = EditorDocumentHighlightingRouter.route( - fileBuffer, - registry.resolve("pbs", analysis.semanticPresentation()), - analysis); - - assertEquals(EditorDocumentHighlightOwner.LSP, result.owner()); - assertTrue(result.inlineHints().isEmpty()); - assertTrue(containsStyle(result.styleSpans(), "editor-semantic-pbs-keyword")); - assertTrue(containsStyle(result.styleSpans(), "editor-semantic-pbs-service")); - assertTrue(containsStyle(result.styleSpans(), "editor-semantic-pbs-function")); - } - - @Test - void frontendDocumentsPreserveTransportedInlineHintsEvenWithoutSemanticHighlightCoverage() { - final EditorDocumentPresentationRegistry registry = new EditorDocumentPresentationRegistry(); - final EditorOpenFileBuffer fileBuffer = new EditorOpenFileBuffer( - Path.of("/tmp/example/src/main.pbs"), - "main.pbs", - "pbs", - "fn main() -> void { let value = 1; }", - "LF", - true, - VfsDocumentAccessMode.READ_ONLY, - false); - - final LspAnalyzeDocumentResult analysis = new LspAnalyzeDocumentResult( - new LspSessionStateDTO(true, List.of("highlight")), - new LspSemanticPresentationDTO( - List.of("pbs-function"), - List.of("/themes/pbs/semantic-highlighting.css")), - List.of(), - List.of(), - List.of(new p.studio.lsp.dtos.LspInlineHintDTO(new LspRangeDTO(24, 29), "int", "type")), - List.of(), - List.of(), - List.of()); - - final EditorDocumentHighlightingResult result = EditorDocumentHighlightingRouter.route( - fileBuffer, - registry.resolve("pbs", analysis.semanticPresentation()), - analysis); - - assertEquals(EditorDocumentHighlightOwner.LOCAL, result.owner()); - assertEquals(1, result.inlineHints().size()); - assertEquals("int", result.inlineHints().getFirst().label()); - } - - @Test - void nonFrontendDocumentsDiscardTransportedInlineHints() { - final EditorDocumentPresentationRegistry registry = new EditorDocumentPresentationRegistry(); - final EditorOpenFileBuffer fileBuffer = new EditorOpenFileBuffer( - Path.of("/tmp/example/prometeu.json"), - "prometeu.json", - "json", - "{\n \"name\": \"Example\"\n}\n", - "LF", - false, - VfsDocumentAccessMode.EDITABLE, - false); - - final LspAnalyzeDocumentResult analysis = new LspAnalyzeDocumentResult( - new LspSessionStateDTO(true, List.of("highlight")), - new LspSemanticPresentationDTO(List.of(), List.of()), - List.of(), - List.of(), - List.of(new p.studio.lsp.dtos.LspInlineHintDTO(new LspRangeDTO(0, 1), "ignored", "type")), - List.of(), - List.of(), - List.of()); - - final EditorDocumentHighlightingResult result = EditorDocumentHighlightingRouter.route( - fileBuffer, - registry.resolve("json"), - analysis); - - assertEquals(EditorDocumentHighlightOwner.LOCAL, result.owner()); - assertTrue(result.inlineHints().isEmpty()); - } - - @Test - void bashBuiltinTestOnlyHighlightsInCommandPosition() { - final EditorDocumentPresentationRegistry registry = new EditorDocumentPresentationRegistry(); - final EditorOpenFileBuffer commandBuffer = new EditorOpenFileBuffer( - Path.of("/tmp/example/run.sh"), - "run.sh", - "bash", - "test -f ./file\n", - "LF", - false, - VfsDocumentAccessMode.EDITABLE, - false); - final EditorOpenFileBuffer plainTextBuffer = new EditorOpenFileBuffer( - Path.of("/tmp/example/run.sh"), - "run.sh", - "bash", - "echo \"$test\"\n", - "LF", - false, - VfsDocumentAccessMode.EDITABLE, - false); - - final EditorDocumentHighlightingResult commandResult = EditorDocumentHighlightingRouter.route( - commandBuffer, - registry.resolve("bash"), - null); - final EditorDocumentHighlightingResult plainTextResult = EditorDocumentHighlightingRouter.route( - plainTextBuffer, - registry.resolve("bash"), - null); - - assertTrue(containsStyle(commandResult.styleSpans(), "editor-syntax-bash-builtin")); - assertFalse(containsStyle(plainTextResult.styleSpans(), "editor-syntax-bash-builtin")); - } - - private boolean containsStyle( - final org.fxmisc.richtext.model.StyleSpans> styleSpans, - final String styleClass) { - for (int index = 0; index < styleSpans.getSpanCount(); index++) { - if (styleSpans.getStyleSpan(index).getStyle().contains(styleClass)) { - return true; - } - } - return false; - } -} diff --git a/prometeu-studio/src/test/java/p/studio/workspaces/editor/EditorDocumentPresentationRegistryTest.java b/prometeu-studio/src/test/java/p/studio/workspaces/editor/EditorDocumentPresentationRegistryTest.java deleted file mode 100644 index 13450c3b..00000000 --- a/prometeu-studio/src/test/java/p/studio/workspaces/editor/EditorDocumentPresentationRegistryTest.java +++ /dev/null @@ -1,60 +0,0 @@ -package p.studio.workspaces.editor; - -import org.junit.jupiter.api.Test; -import p.studio.lsp.dtos.LspSemanticPresentationDTO; - -import static org.junit.jupiter.api.Assertions.assertEquals; -import static org.junit.jupiter.api.Assertions.assertTrue; - -final class EditorDocumentPresentationRegistryTest { - private final EditorDocumentPresentationRegistry registry = new EditorDocumentPresentationRegistry(); - - @Test - void resolvesFrontendTypeIdsToFrontendPresentation() { - final EditorDocumentPresentation presentation = registry.resolve( - "pbs", - new LspSemanticPresentationDTO( - java.util.List.of("pbs-keyword", "pbs-service"), - java.util.List.of("/themes/pbs/semantic-highlighting.css"))); - - assertEquals("pbs", presentation.styleKey()); - assertEquals(java.util.List.of("pbs-keyword", "pbs-service"), presentation.semanticKeys()); - assertEquals(1, presentation.stylesheetUrls().size()); - assertTrue(presentation.stylesheetUrls().getFirst().endsWith("/themes/pbs/semantic-highlighting.css")); - } - - @Test - void missingFrontendResourcesFallbackToFrontendOwnedPresentationResources() { - final EditorDocumentPresentation presentation = registry.resolve( - "pbs", - new LspSemanticPresentationDTO( - java.util.List.of("pbs-keyword"), - java.util.List.of("/themes/pbs/missing.css"))); - - assertEquals("pbs", presentation.styleKey()); - assertEquals(java.util.List.of("pbs-keyword"), presentation.semanticKeys()); - assertEquals(1, presentation.stylesheetUrls().size()); - assertTrue(presentation.highlight("fn main() -> void {}").getStyleSpan(0).getStyle().isEmpty()); - } - - @Test - void resolvesJsonTypeIdsToJsonPresentation() { - final EditorDocumentPresentation presentation = registry.resolve("json"); - - assertEquals("json", presentation.styleKey()); - assertEquals(1, presentation.stylesheetUrls().size()); - } - - @Test - void resolvesBashTypeIdsToBashPresentation() { - final EditorDocumentPresentation presentation = registry.resolve("bash"); - - assertEquals("bash", presentation.styleKey()); - assertEquals(1, presentation.stylesheetUrls().size()); - } - - @Test - void fallsBackToTextPresentationForUnknownTypeIds() { - assertEquals("text", registry.resolve("markdown").styleKey()); - } -} diff --git a/prometeu-studio/src/test/java/p/studio/workspaces/editor/EditorDocumentScopeGuideModelTest.java b/prometeu-studio/src/test/java/p/studio/workspaces/editor/EditorDocumentScopeGuideModelTest.java deleted file mode 100644 index b5efe311..00000000 --- a/prometeu-studio/src/test/java/p/studio/workspaces/editor/EditorDocumentScopeGuideModelTest.java +++ /dev/null @@ -1,166 +0,0 @@ -package p.studio.workspaces.editor; - -import org.junit.jupiter.api.Test; -import p.studio.lsp.dtos.LspRangeDTO; -import p.studio.lsp.dtos.LspStructuralAnchorDTO; -import p.studio.lsp.dtos.LspSymbolDTO; -import p.studio.lsp.messages.LspSymbolKind; - -import java.nio.file.Path; -import java.util.List; - -import static org.junit.jupiter.api.Assertions.assertEquals; -import static org.junit.jupiter.api.Assertions.assertNull; - -final class EditorDocumentScopeGuideModelTest { - @Test - void selectsActiveScopeAsSmallestContainingRange() { - final String content = """ - struct Hero { - fn attack() { - let value = 1 - } - } - - enum Kind { - Unit - } - """; - final LspSymbolDTO attack = symbol(content, "fn attack()", "}", LspSymbolKind.METHOD, List.of()); - final LspSymbolDTO hero = new LspSymbolDTO( - "struct Hero", - LspSymbolKind.STRUCT, - Path.of("/tmp/example/main.pbs"), - new LspRangeDTO( - content.indexOf("struct Hero"), - content.indexOf("\n\nenum Kind")), - List.of(attack)); - final LspSymbolDTO kind = symbol(content, "enum Kind", "}\n", LspSymbolKind.ENUM, List.of()); - - final EditorDocumentScopeGuideModel model = EditorDocumentScopeGuideModel.from(content, List.of(hero, kind)); - final EditorDocumentScopeGuideModel.ActiveGuides guides = model.resolveActiveGuides(content.indexOf("let value")); - - assertEquals(content.indexOf("fn attack()"), guides.activeScope().startOffset()); - assertEquals(content.indexOf("struct Hero"), guides.activeContainer().startOffset()); - } - - @Test - void omitsActiveContainerWhenScopeHasNoParent() { - final String content = """ - struct Hero { - hp: Int - } - """; - final LspSymbolDTO symbol = new LspSymbolDTO( - "struct Hero", - LspSymbolKind.STRUCT, - Path.of("/tmp/example/main.pbs"), - new LspRangeDTO(0, content.length()), - List.of()); - - final EditorDocumentScopeGuideModel model = EditorDocumentScopeGuideModel.from(content, List.of(symbol)); - final EditorDocumentScopeGuideModel.ActiveGuides guides = model.resolveActiveGuides(content.indexOf("hp")); - - assertEquals(content.indexOf("struct Hero"), guides.activeScope().startOffset()); - assertNull(guides.activeContainer()); - } - - @Test - void exposesAtMostTwoActiveSegmentsPerLine() { - final String content = """ - struct Hero { - fn attack() { - let value = 1 - } - } - """; - final LspSymbolDTO attack = symbol(content, "fn attack()", "}", LspSymbolKind.METHOD, List.of()); - final LspSymbolDTO hero = new LspSymbolDTO( - "struct Hero", - LspSymbolKind.STRUCT, - Path.of("/tmp/example/main.pbs"), - new LspRangeDTO(0, content.length()), - List.of(attack)); - - final EditorDocumentScopeGuideModel model = EditorDocumentScopeGuideModel.from(content, List.of(hero)); - final EditorDocumentScopeGuideModel.ActiveGuides guides = model.resolveActiveGuides(content.indexOf("let value")); - - assertSegments(model, 1, guides, "ACTIVE_CONTAINER:CONTINUE", "ACTIVE_SCOPE:START"); - assertSegments(model, 2, guides, "ACTIVE_CONTAINER:CONTINUE", "ACTIVE_SCOPE:CONTINUE"); - assertSegments(model, 3, guides, "ACTIVE_CONTAINER:CONTINUE", "ACTIVE_SCOPE:END"); - } - - @Test - void ignoresSingleLineAndUnknownSymbols() { - final String content = """ - if ready { - value() - } - """; - final LspSymbolDTO symbol = new LspSymbolDTO( - "if ready", - LspSymbolKind.UNKNOWN, - Path.of("/tmp/example/main.pbs"), - new LspRangeDTO(0, content.length()), - List.of()); - - final EditorDocumentScopeGuideModel model = EditorDocumentScopeGuideModel.from(content, List.of(symbol)); - - assertEquals(EditorDocumentScopeGuideModel.ActiveGuides.empty(), model.resolveActiveGuides(content.indexOf("value"))); - } - - @Test - void structuralAnchorsDriveGuideStartAndEndLines() { - final String content = """ - fn main( - value: int - ) -> void - { - helper(); - } - """; - final LspStructuralAnchorDTO anchor = new LspStructuralAnchorDTO( - new LspRangeDTO(content.indexOf("fn main"), content.length()), - new LspRangeDTO(content.indexOf("{"), content.indexOf("{") + 1), - new LspRangeDTO(content.indexOf("}"), content.indexOf("}") + 1), - List.of()); - - final EditorDocumentScopeGuideModel model = EditorDocumentScopeGuideModel.fromStructuralAnchors(content, List.of(anchor)); - final EditorDocumentScopeGuideModel.ActiveGuides guides = model.resolveActiveGuides(content.indexOf("helper")); - - assertSegments(model, 0, guides); - assertSegments(model, 1, guides); - assertSegments(model, 2, guides); - assertSegments(model, 3, guides, "ACTIVE_SCOPE:START"); - assertSegments(model, 4, guides, "ACTIVE_SCOPE:CONTINUE"); - assertSegments(model, 5, guides, "ACTIVE_SCOPE:END"); - } - - private static LspSymbolDTO symbol( - final String content, - final String startMarker, - final String endMarker, - final LspSymbolKind kind, - final List children) { - final int start = content.indexOf(startMarker); - final int end = content.indexOf(endMarker, start) + endMarker.length(); - return new LspSymbolDTO( - startMarker, - kind, - Path.of("/tmp/example/main.pbs"), - new LspRangeDTO(start, end), - children); - } - - private static void assertSegments( - final EditorDocumentScopeGuideModel model, - final int line, - final EditorDocumentScopeGuideModel.ActiveGuides guides, - final String... expectedKinds) { - assertEquals( - List.of(expectedKinds), - model.segmentsForLine(line, guides).stream() - .map(segment -> segment.role().name() + ":" + segment.kind().name()) - .toList()); - } -} diff --git a/prometeu-studio/src/test/java/p/studio/workspaces/editor/EditorInlineHintLayoutTest.java b/prometeu-studio/src/test/java/p/studio/workspaces/editor/EditorInlineHintLayoutTest.java deleted file mode 100644 index 7bcc9c23..00000000 --- a/prometeu-studio/src/test/java/p/studio/workspaces/editor/EditorInlineHintLayoutTest.java +++ /dev/null @@ -1,44 +0,0 @@ -package p.studio.workspaces.editor; - -import org.junit.jupiter.api.Test; -import p.studio.lsp.dtos.LspInlineHintDTO; -import p.studio.lsp.dtos.LspRangeDTO; - -import java.util.List; -import java.util.Optional; - -import static org.junit.jupiter.api.Assertions.assertEquals; - -final class EditorInlineHintLayoutTest { - @Test - void layoutCreatesDecorativePlacementsForHintsWithResolvedAnchors() { - final var hint = new LspInlineHintDTO(new LspRangeDTO(10, 15), "int", "type"); - - final var placements = EditorInlineHintLayout.layout( - List.of(hint), - ignored -> Optional.of(new EditorInlineHintLayout.AnchorBounds(20.0d, 8.0d, 40.0d, 16.0d))); - - assertEquals(1, placements.size()); - assertEquals(": int", placements.getFirst().displayText()); - assertEquals("editor-inline-hint-type", placements.getFirst().categoryStyleClass()); - assertEquals(46.0d, placements.getFirst().screenX()); - assertEquals(8.0d, placements.getFirst().screenY()); - assertEquals(16.0d, placements.getFirst().anchorHeight()); - } - - @Test - void layoutKeepsValidHintsWhenOnlySomeAnchorsResolve() { - final var stable = new LspInlineHintDTO(new LspRangeDTO(10, 15), "int", "type"); - final var missing = new LspInlineHintDTO(new LspRangeDTO(30, 35), "Player", "type"); - - final var placements = EditorInlineHintLayout.layout( - List.of(stable, missing), - hint -> hint == stable - ? Optional.of(new EditorInlineHintLayout.AnchorBounds(12.0d, 4.0d, 28.0d, 14.0d)) - : Optional.empty()); - - assertEquals(1, placements.size()); - assertEquals(stable, placements.getFirst().inlineHint()); - assertEquals(": int", placements.getFirst().displayText()); - } -} diff --git a/prometeu-studio/src/test/java/p/studio/workspaces/editor/EditorOpenFileSessionTest.java b/prometeu-studio/src/test/java/p/studio/workspaces/editor/EditorOpenFileSessionTest.java deleted file mode 100644 index c793092e..00000000 --- a/prometeu-studio/src/test/java/p/studio/workspaces/editor/EditorOpenFileSessionTest.java +++ /dev/null @@ -1,140 +0,0 @@ -package p.studio.workspaces.editor; - -import org.junit.jupiter.api.Test; -import p.studio.vfs.messages.VfsDocumentAccessMode; - -import java.nio.file.Path; -import java.util.List; - -import static org.junit.jupiter.api.Assertions.*; - -final class EditorOpenFileSessionTest { - - @Test - void openAddsNewFileAndMarksItActive() { - final var session = new EditorOpenFileSession(); - final var file = fileBuffer(Path.of("src/main.pbs"), "main.pbs", VfsDocumentAccessMode.EDITABLE, false, true, "fn main(): void\n"); - - session.open(file); - - assertEquals(1, session.openFiles().size()); - assertEquals(file.path().toAbsolutePath().normalize(), session.activeFile().orElseThrow().path()); - } - - @Test - void openDoesNotDuplicateExistingTab() { - final var session = new EditorOpenFileSession(); - final var first = fileBuffer(Path.of("src/main.pbs"), "main.pbs", VfsDocumentAccessMode.EDITABLE, false, true, "a"); - final var second = fileBuffer(Path.of("src/main.pbs"), "main.pbs", VfsDocumentAccessMode.EDITABLE, false, true, "b"); - - session.open(first); - session.open(second); - - assertEquals(1, session.openFiles().size()); - assertEquals(first.path().toAbsolutePath().normalize(), session.activeFile().orElseThrow().path()); - assertEquals("b", session.activeFile().orElseThrow().content()); - } - - @Test - void activateSwitchesTheActiveTabWithinTheCurrentSession() { - final var session = new EditorOpenFileSession(); - final var first = fileBuffer(Path.of("src/main.pbs"), "main.pbs", VfsDocumentAccessMode.EDITABLE, false, true, "a"); - final var second = fileBuffer(Path.of("src/other.pbs"), "other.pbs", VfsDocumentAccessMode.EDITABLE, false, true, "b"); - - session.open(first); - session.open(second); - session.activate(first.path()); - - assertEquals(first.path().toAbsolutePath().normalize(), session.activeFile().orElseThrow().path()); - } - - @Test - void reportsSaveStateForDirtyEditableFilesOnly() { - final var session = new EditorOpenFileSession(); - session.open(fileBuffer(Path.of("notes.txt"), "notes.txt", VfsDocumentAccessMode.EDITABLE, true, false, "alpha")); - - assertTrue(session.hasSaveableActiveFile()); - assertTrue(session.hasDirtyEditableFiles()); - } - - @Test - void frontendEditableFilesParticipateInSaveStateWhenDirty() { - final var session = new EditorOpenFileSession(); - session.open(fileBuffer(Path.of("src/main.pbs"), "main.pbs", VfsDocumentAccessMode.EDITABLE, true, true, "fn main(): void")); - - assertTrue(session.hasSaveableActiveFile()); - assertTrue(session.hasDirtyEditableFiles()); - assertTrue(session.activeFile().orElseThrow().frontendDocument()); - assertTrue(session.activeFile().orElseThrow().editable()); - } - - @Test - void closeRemovesInactiveTabWithoutChangingTheActiveTab() { - final var session = new EditorOpenFileSession(); - final var first = fileBuffer(Path.of("src/main.pbs"), "main.pbs", VfsDocumentAccessMode.EDITABLE, false, true, "a"); - final var second = fileBuffer(Path.of("README.md"), "README.md", VfsDocumentAccessMode.EDITABLE, false, false, "b"); - - session.open(first); - session.open(second); - session.close(first.path()); - - assertEquals(1, session.openFiles().size()); - assertEquals(second.path().toAbsolutePath().normalize(), session.activeFile().orElseThrow().path()); - } - - @Test - void closePromotesTheNextTabWhenTheActiveTabIsClosed() { - final var session = new EditorOpenFileSession(); - final var first = fileBuffer(Path.of("src/main.pbs"), "main.pbs", VfsDocumentAccessMode.EDITABLE, false, true, "a"); - final var second = fileBuffer(Path.of("README.md"), "README.md", VfsDocumentAccessMode.EDITABLE, false, false, "b"); - final var third = fileBuffer(Path.of("notes.txt"), "notes.txt", VfsDocumentAccessMode.EDITABLE, false, false, "c"); - - session.open(first); - session.open(second); - session.open(third); - session.activate(second.path()); - session.close(second.path()); - - assertEquals(List.of( - first.path().toAbsolutePath().normalize(), - third.path().toAbsolutePath().normalize()), - session.openFiles().stream().map(EditorOpenFileBuffer::path).toList()); - assertEquals(third.path().toAbsolutePath().normalize(), session.activeFile().orElseThrow().path()); - } - - @Test - void exportsRestorationStateFromOpenTabsAndActiveTab() { - final var session = new EditorOpenFileSession(); - final var first = fileBuffer(Path.of("src/main.pbs"), "main.pbs", VfsDocumentAccessMode.EDITABLE, false, true, "a"); - final var second = fileBuffer(Path.of("README.md"), "README.md", VfsDocumentAccessMode.EDITABLE, false, false, "b"); - - session.open(first); - session.open(second); - session.activate(first.path()); - - final var restorationState = session.restorationState(); - - assertEquals(List.of( - first.path().toAbsolutePath().normalize().toString(), - second.path().toAbsolutePath().normalize().toString()), restorationState.openTabPaths()); - assertEquals(first.path().toAbsolutePath().normalize().toString(), restorationState.activeTabPath()); - } - - private EditorOpenFileBuffer fileBuffer( - final Path path, - final String tabLabel, - final VfsDocumentAccessMode accessMode, - final boolean dirty, - final boolean frontendDocument, - final String content) { - return new EditorOpenFileBuffer( - path, - tabLabel, - frontendDocument ? "pbs" : "text", - content, - "LF", - frontendDocument, - accessMode, - dirty); - } -} -- 2.47.2 From 1f85be37210fceda20c9a4a6818a0705a5c1e755 Mon Sep 17 00:00:00 2001 From: bQUARKz Date: Tue, 5 May 2026 11:14:45 +0100 Subject: [PATCH 02/37] implements PLN-0063 --- discussion/index.ndjson | 2 +- ...odule-removal-with-runtime-preservation.md | 15 +- prometeu-app/build.gradle.kts | 6 +- .../prometeu-lsp-api/build.gradle.kts | 7 - .../main/java/p/studio/lsp/LspService.java | 21 - .../java/p/studio/lsp/LspServiceFactory.java | 8 - .../lsp/dtos/LspDefinitionTargetDTO.java | 16 - .../p/studio/lsp/dtos/LspDiagnosticDTO.java | 24 - .../studio/lsp/dtos/LspHighlightSpanDTO.java | 13 - .../p/studio/lsp/dtos/LspInlineHintDTO.java | 18 - .../java/p/studio/lsp/dtos/LspRangeDTO.java | 15 - .../lsp/dtos/LspSemanticPresentationDTO.java | 14 - .../p/studio/lsp/dtos/LspSessionStateDTO.java | 13 - .../lsp/dtos/LspStructuralAnchorDTO.java | 18 - .../java/p/studio/lsp/dtos/LspSymbolDTO.java | 23 - .../java/p/studio/lsp/events/LspEvent.java | 13 - .../p/studio/lsp/events/LspEventKind.java | 5 - .../p/studio/lsp/events/LspEventSink.java | 5 - .../messages/LspAnalyzeDocumentRequest.java | 12 - .../messages/LspAnalyzeDocumentResult.java | 34 - .../lsp/messages/LspDefinitionRequest.java | 14 - .../lsp/messages/LspDefinitionResult.java | 19 - .../lsp/messages/LspDiagnosticSeverity.java | 6 - .../lsp/messages/LspProjectContext.java | 16 - .../p/studio/lsp/messages/LspSymbolKind.java | 24 - .../studio/lsp/dtos/LspInlineHintDTOTest.java | 22 - prometeu-lsp/prometeu-lsp-v1/build.gradle.kts | 16 - .../studio/lsp/LspSemanticAnalyseService.java | 27 - .../lsp/LspSemanticDefinitionService.java | 46 -- .../p/studio/lsp/LspSemanticReadPhase.java | 353 ---------- .../p/studio/lsp/LspSemanticUtilities.java | 52 -- .../p/studio/lsp/LspServiceFactoryImpl.java | 17 - .../java/p/studio/lsp/LspServiceImpl.java | 50 -- .../lsp/OverlaySourceProviderFactoryImpl.java | 51 -- .../studio/lsp/messages/SemanticSession.java | 26 - .../lsp/models/AnalysisRuntimeSnapshot.java | 11 - .../p/studio/lsp/models/SemanticIndex.java | 635 ------------------ .../java/p/studio/lsp/LspServiceImplTest.java | 427 ------------ prometeu-studio/build.gradle.kts | 2 - .../p/studio/projects/ProjectReference.java | 5 - .../prometeu-vfs-api/build.gradle.kts | 3 - .../studio/vfs/ProjectDocumentVfsFactory.java | 7 - .../p/studio/vfs/VfsDocumentOpenResult.java | 40 -- .../java/p/studio/vfs/VfsProjectDocument.java | 47 -- .../messages/VfsDocumentAccessContext.java | 20 - .../vfs/messages/VfsDocumentAccessMode.java | 6 - .../vfs/messages/VfsDocumentSaveResult.java | 16 - .../vfs/messages/VfsDocumentSaveStatus.java | 7 - .../vfs/messages/VfsDocumentTypeIds.java | 11 - .../vfs/messages/VfsProjectContext.java | 16 - .../p/studio/vfs/messages/VfsProjectNode.java | 19 - .../vfs/messages/VfsProjectSnapshot.java | 14 - .../vfs/messages/VfsRefreshRequest.java | 10 - .../vfs/messages/VfsUnsupportedReason.java | 10 - prometeu-vfs/prometeu-vfs-v1/build.gradle.kts | 9 - .../FilesystemProjectDocumentVfsFactory.java | 12 - .../vfs/FilesystemVfsProjectDocument.java | 466 ------------- .../vfs/FilesystemVfsProjectDocumentTest.java | 237 ------- settings.gradle.kts | 4 - 59 files changed, 9 insertions(+), 3046 deletions(-) delete mode 100644 prometeu-lsp/prometeu-lsp-api/build.gradle.kts delete mode 100644 prometeu-lsp/prometeu-lsp-api/src/main/java/p/studio/lsp/LspService.java delete mode 100644 prometeu-lsp/prometeu-lsp-api/src/main/java/p/studio/lsp/LspServiceFactory.java delete mode 100644 prometeu-lsp/prometeu-lsp-api/src/main/java/p/studio/lsp/dtos/LspDefinitionTargetDTO.java delete mode 100644 prometeu-lsp/prometeu-lsp-api/src/main/java/p/studio/lsp/dtos/LspDiagnosticDTO.java delete mode 100644 prometeu-lsp/prometeu-lsp-api/src/main/java/p/studio/lsp/dtos/LspHighlightSpanDTO.java delete mode 100644 prometeu-lsp/prometeu-lsp-api/src/main/java/p/studio/lsp/dtos/LspInlineHintDTO.java delete mode 100644 prometeu-lsp/prometeu-lsp-api/src/main/java/p/studio/lsp/dtos/LspRangeDTO.java delete mode 100644 prometeu-lsp/prometeu-lsp-api/src/main/java/p/studio/lsp/dtos/LspSemanticPresentationDTO.java delete mode 100644 prometeu-lsp/prometeu-lsp-api/src/main/java/p/studio/lsp/dtos/LspSessionStateDTO.java delete mode 100644 prometeu-lsp/prometeu-lsp-api/src/main/java/p/studio/lsp/dtos/LspStructuralAnchorDTO.java delete mode 100644 prometeu-lsp/prometeu-lsp-api/src/main/java/p/studio/lsp/dtos/LspSymbolDTO.java delete mode 100644 prometeu-lsp/prometeu-lsp-api/src/main/java/p/studio/lsp/events/LspEvent.java delete mode 100644 prometeu-lsp/prometeu-lsp-api/src/main/java/p/studio/lsp/events/LspEventKind.java delete mode 100644 prometeu-lsp/prometeu-lsp-api/src/main/java/p/studio/lsp/events/LspEventSink.java delete mode 100644 prometeu-lsp/prometeu-lsp-api/src/main/java/p/studio/lsp/messages/LspAnalyzeDocumentRequest.java delete mode 100644 prometeu-lsp/prometeu-lsp-api/src/main/java/p/studio/lsp/messages/LspAnalyzeDocumentResult.java delete mode 100644 prometeu-lsp/prometeu-lsp-api/src/main/java/p/studio/lsp/messages/LspDefinitionRequest.java delete mode 100644 prometeu-lsp/prometeu-lsp-api/src/main/java/p/studio/lsp/messages/LspDefinitionResult.java delete mode 100644 prometeu-lsp/prometeu-lsp-api/src/main/java/p/studio/lsp/messages/LspDiagnosticSeverity.java delete mode 100644 prometeu-lsp/prometeu-lsp-api/src/main/java/p/studio/lsp/messages/LspProjectContext.java delete mode 100644 prometeu-lsp/prometeu-lsp-api/src/main/java/p/studio/lsp/messages/LspSymbolKind.java delete mode 100644 prometeu-lsp/prometeu-lsp-api/src/test/java/p/studio/lsp/dtos/LspInlineHintDTOTest.java delete mode 100644 prometeu-lsp/prometeu-lsp-v1/build.gradle.kts delete mode 100644 prometeu-lsp/prometeu-lsp-v1/src/main/java/p/studio/lsp/LspSemanticAnalyseService.java delete mode 100644 prometeu-lsp/prometeu-lsp-v1/src/main/java/p/studio/lsp/LspSemanticDefinitionService.java delete mode 100644 prometeu-lsp/prometeu-lsp-v1/src/main/java/p/studio/lsp/LspSemanticReadPhase.java delete mode 100644 prometeu-lsp/prometeu-lsp-v1/src/main/java/p/studio/lsp/LspSemanticUtilities.java delete mode 100644 prometeu-lsp/prometeu-lsp-v1/src/main/java/p/studio/lsp/LspServiceFactoryImpl.java delete mode 100644 prometeu-lsp/prometeu-lsp-v1/src/main/java/p/studio/lsp/LspServiceImpl.java delete mode 100644 prometeu-lsp/prometeu-lsp-v1/src/main/java/p/studio/lsp/OverlaySourceProviderFactoryImpl.java delete mode 100644 prometeu-lsp/prometeu-lsp-v1/src/main/java/p/studio/lsp/messages/SemanticSession.java delete mode 100644 prometeu-lsp/prometeu-lsp-v1/src/main/java/p/studio/lsp/models/AnalysisRuntimeSnapshot.java delete mode 100644 prometeu-lsp/prometeu-lsp-v1/src/main/java/p/studio/lsp/models/SemanticIndex.java delete mode 100644 prometeu-lsp/prometeu-lsp-v1/src/test/java/p/studio/lsp/LspServiceImplTest.java delete mode 100644 prometeu-vfs/prometeu-vfs-api/build.gradle.kts delete mode 100644 prometeu-vfs/prometeu-vfs-api/src/main/java/p/studio/vfs/ProjectDocumentVfsFactory.java delete mode 100644 prometeu-vfs/prometeu-vfs-api/src/main/java/p/studio/vfs/VfsDocumentOpenResult.java delete mode 100644 prometeu-vfs/prometeu-vfs-api/src/main/java/p/studio/vfs/VfsProjectDocument.java delete mode 100644 prometeu-vfs/prometeu-vfs-api/src/main/java/p/studio/vfs/messages/VfsDocumentAccessContext.java delete mode 100644 prometeu-vfs/prometeu-vfs-api/src/main/java/p/studio/vfs/messages/VfsDocumentAccessMode.java delete mode 100644 prometeu-vfs/prometeu-vfs-api/src/main/java/p/studio/vfs/messages/VfsDocumentSaveResult.java delete mode 100644 prometeu-vfs/prometeu-vfs-api/src/main/java/p/studio/vfs/messages/VfsDocumentSaveStatus.java delete mode 100644 prometeu-vfs/prometeu-vfs-api/src/main/java/p/studio/vfs/messages/VfsDocumentTypeIds.java delete mode 100644 prometeu-vfs/prometeu-vfs-api/src/main/java/p/studio/vfs/messages/VfsProjectContext.java delete mode 100644 prometeu-vfs/prometeu-vfs-api/src/main/java/p/studio/vfs/messages/VfsProjectNode.java delete mode 100644 prometeu-vfs/prometeu-vfs-api/src/main/java/p/studio/vfs/messages/VfsProjectSnapshot.java delete mode 100644 prometeu-vfs/prometeu-vfs-api/src/main/java/p/studio/vfs/messages/VfsRefreshRequest.java delete mode 100644 prometeu-vfs/prometeu-vfs-api/src/main/java/p/studio/vfs/messages/VfsUnsupportedReason.java delete mode 100644 prometeu-vfs/prometeu-vfs-v1/build.gradle.kts delete mode 100644 prometeu-vfs/prometeu-vfs-v1/src/main/java/p/studio/vfs/FilesystemProjectDocumentVfsFactory.java delete mode 100644 prometeu-vfs/prometeu-vfs-v1/src/main/java/p/studio/vfs/FilesystemVfsProjectDocument.java delete mode 100644 prometeu-vfs/prometeu-vfs-v1/src/test/java/p/studio/vfs/FilesystemVfsProjectDocumentTest.java diff --git a/discussion/index.ndjson b/discussion/index.ndjson index a0100ba9..0b06bb11 100644 --- a/discussion/index.ndjson +++ b/discussion/index.ndjson @@ -1,5 +1,5 @@ {"type":"meta","next_id":{"DSC":32,"AGD":35,"DEC":32,"PLN":65,"LSN":47,"CLSN":1}} -{"type":"discussion","id":"DSC-0031","status":"in_progress","ticket":"studio-editor-workspace-cleanup","title":"Limpeza completa do Workspace Editor do Studio e remoção dos acoplamentos legados","created_at":"2026-05-05","updated_at":"2026-05-05","tags":["studio","editor","cleanup","vfs","lsp","migration"],"agendas":[{"id":"AGD-0034","file":"AGD-0034-vscode-editor-migration-feasibility.md","status":"accepted","created_at":"2026-05-05","updated_at":"2026-05-05"}],"decisions":[{"id":"DEC-0031","file":"DEC-0031-studio-editor-workspace-cleanup.md","status":"in_progress","created_at":"2026-05-05","updated_at":"2026-05-05","ref_agenda":"AGD-0034"}],"plans":[{"id":"PLN-0062","file":"PLN-0062-shell-session-and-state-cleanup-after-editor-removal.md","status":"done","created_at":"2026-05-05","updated_at":"2026-05-05","ref_decisions":["DEC-0031"]},{"id":"PLN-0063","file":"PLN-0063-legacy-lsp-and-vfs-module-removal-with-runtime-preservation.md","status":"open","created_at":"2026-05-05","updated_at":"2026-05-05","ref_decisions":["DEC-0031"]},{"id":"PLN-0064","file":"PLN-0064-normative-test-and-lesson-cleanup-for-editor-stack-removal.md","status":"open","created_at":"2026-05-05","updated_at":"2026-05-05","ref_decisions":["DEC-0031"]}],"lessons":[]} +{"type":"discussion","id":"DSC-0031","status":"in_progress","ticket":"studio-editor-workspace-cleanup","title":"Limpeza completa do Workspace Editor do Studio e remoção dos acoplamentos legados","created_at":"2026-05-05","updated_at":"2026-05-05","tags":["studio","editor","cleanup","vfs","lsp","migration"],"agendas":[{"id":"AGD-0034","file":"AGD-0034-vscode-editor-migration-feasibility.md","status":"accepted","created_at":"2026-05-05","updated_at":"2026-05-05"}],"decisions":[{"id":"DEC-0031","file":"DEC-0031-studio-editor-workspace-cleanup.md","status":"in_progress","created_at":"2026-05-05","updated_at":"2026-05-05","ref_agenda":"AGD-0034"}],"plans":[{"id":"PLN-0062","file":"PLN-0062-shell-session-and-state-cleanup-after-editor-removal.md","status":"done","created_at":"2026-05-05","updated_at":"2026-05-05","ref_decisions":["DEC-0031"]},{"id":"PLN-0063","file":"PLN-0063-legacy-lsp-and-vfs-module-removal-with-runtime-preservation.md","status":"done","created_at":"2026-05-05","updated_at":"2026-05-05","ref_decisions":["DEC-0031"]},{"id":"PLN-0064","file":"PLN-0064-normative-test-and-lesson-cleanup-for-editor-stack-removal.md","status":"open","created_at":"2026-05-05","updated_at":"2026-05-05","ref_decisions":["DEC-0031"]}],"lessons":[]} {"type":"discussion","id":"DSC-0030","status":"done","ticket":"studio-scene-pack-runtime-binary-contract","title":"Studio scene pack contract for runtime SCENE binary payload","created_at":"2026-04-24","updated_at":"2026-05-01","tags":["studio","packer","runtime","scene","asset-pack","binary-format","tiled"],"agendas":[],"decisions":[],"plans":[],"lessons":[{"id":"LSN-0046","file":"discussion/lessons/DSC-0030-studio-scene-pack-runtime-binary-contract/LSN-0046-canonical-scene-owns-editorial-truth-while-pack-stays-request-driven.md","status":"done","created_at":"2026-05-01","updated_at":"2026-05-01"}]} {"type":"discussion","id":"DSC-0029","status":"done","ticket":"studio-frame-composer-syscall-and-sprite-alignment","title":"Studio Alignment with Runtime FrameComposer Syscalls and Sprite Composition","created_at":"2026-04-18","updated_at":"2026-04-18","tags":["studio","compiler","pbs","stdlib","runtime-alignment","abi","syscall","frame-composer","sprites"],"agendas":[],"decisions":[],"plans":[],"lessons":[{"id":"LSN-0041","file":"discussion/lessons/DSC-0029-studio-frame-composer-syscall-and-sprite-alignment/LSN-0041-composer-must-own-public-sprite-composition.md","status":"done","created_at":"2026-04-18","updated_at":"2026-04-18"}]} {"type":"discussion","id":"DSC-0028","status":"done","ticket":"studio-tiled-parser-assets-scene-asset-type","title":"Tiled Parser and Scene Asset-Type Ownership in Assets Workspace","created_at":"2026-04-15","updated_at":"2026-04-23","tags":["studio","assets","scene","tiled","parser","asset-type"],"agendas":[],"decisions":[],"plans":[],"lessons":[{"id":"LSN-0045","file":"discussion/lessons/DSC-0028-studio-tiled-parser-assets-scene-asset-type/LSN-0045-asset-owned-scene-bank-and-tiled-xml-workflow.md","status":"done","created_at":"2026-04-23","updated_at":"2026-04-23"}]} diff --git a/discussion/workflow/plans/PLN-0063-legacy-lsp-and-vfs-module-removal-with-runtime-preservation.md b/discussion/workflow/plans/PLN-0063-legacy-lsp-and-vfs-module-removal-with-runtime-preservation.md index 1429643b..62122162 100644 --- a/discussion/workflow/plans/PLN-0063-legacy-lsp-and-vfs-module-removal-with-runtime-preservation.md +++ b/discussion/workflow/plans/PLN-0063-legacy-lsp-and-vfs-module-removal-with-runtime-preservation.md @@ -2,9 +2,9 @@ id: PLN-0063 ticket: studio-editor-workspace-cleanup title: Legacy LSP and VFS Module Removal with Runtime Preservation -status: open +status: done created: 2026-05-05 -completed: +completed: 2026-05-05 tags: [studio, editor, cleanup, lsp, vfs, runtime] --- @@ -73,11 +73,11 @@ Remove the legacy `prometeu-lsp` and `prometeu-vfs` modules and all remaining co ## Acceptance Criteria -- [ ] `prometeu-lsp` is no longer part of the build graph. -- [ ] `prometeu-vfs` is no longer part of the build graph. -- [ ] No production Studio class imports legacy `LSP` or `VFS` module types. -- [ ] Compiler and shipper build flows still work. -- [ ] Play/run/debug flows still work without the removed modules. +- [x] `prometeu-lsp` is no longer part of the build graph. +- [x] `prometeu-vfs` is no longer part of the build graph. +- [x] No production Studio class imports legacy `LSP` or `VFS` module types. +- [x] Compiler and shipper build flows still work. +- [x] Play/run/debug flows still work without the removed modules. ## Dependencies @@ -89,4 +89,3 @@ Remove the legacy `prometeu-lsp` and `prometeu-vfs` modules and all remaining co - Hidden transitive dependencies may keep the build graph coupled to removed modules longer than expected. - Runtime or debug flows may have indirect event or session assumptions not obvious from imports alone. - Deleting modules too early may obscure compile errors that should instead be fixed in surviving Studio code first. - diff --git a/prometeu-app/build.gradle.kts b/prometeu-app/build.gradle.kts index 253ad5e0..59d3d29b 100644 --- a/prometeu-app/build.gradle.kts +++ b/prometeu-app/build.gradle.kts @@ -5,10 +5,6 @@ plugins { dependencies { implementation(project(":prometeu-infra")) - implementation(project(":prometeu-lsp:prometeu-lsp-api")) - implementation(project(":prometeu-lsp:prometeu-lsp-v1")) - implementation(project(":prometeu-vfs:prometeu-vfs-api")) - implementation(project(":prometeu-vfs:prometeu-vfs-v1")) implementation(project(":prometeu-packer:prometeu-packer-api")) implementation(project(":prometeu-packer:prometeu-packer-v1")) implementation(project(":prometeu-studio")) @@ -23,4 +19,4 @@ application { javafx { version = libs.versions.javafx.get() modules("javafx.controls", "javafx.fxml") -} \ No newline at end of file +} diff --git a/prometeu-lsp/prometeu-lsp-api/build.gradle.kts b/prometeu-lsp/prometeu-lsp-api/build.gradle.kts deleted file mode 100644 index cc7fab83..00000000 --- a/prometeu-lsp/prometeu-lsp-api/build.gradle.kts +++ /dev/null @@ -1,7 +0,0 @@ -plugins { - id("gradle.java-library-conventions") -} - -dependencies { - implementation(project(":prometeu-vfs:prometeu-vfs-api")) -} diff --git a/prometeu-lsp/prometeu-lsp-api/src/main/java/p/studio/lsp/LspService.java b/prometeu-lsp/prometeu-lsp-api/src/main/java/p/studio/lsp/LspService.java deleted file mode 100644 index 7c6ca613..00000000 --- a/prometeu-lsp/prometeu-lsp-api/src/main/java/p/studio/lsp/LspService.java +++ /dev/null @@ -1,21 +0,0 @@ -package p.studio.lsp; - -import p.studio.lsp.dtos.LspSessionStateDTO; -import p.studio.lsp.messages.*; -import p.studio.vfs.VfsProjectDocument; - -public interface LspService extends AutoCloseable { - LspProjectContext projectContext(); - - VfsProjectDocument projectDocumentVfs(); - - LspSessionStateDTO snapshot(); - - LspAnalyzeDocumentResult analyzeDocument(LspAnalyzeDocumentRequest request); - - LspDefinitionResult definition(LspDefinitionRequest request); - - @Override - default void close() { - } -} diff --git a/prometeu-lsp/prometeu-lsp-api/src/main/java/p/studio/lsp/LspServiceFactory.java b/prometeu-lsp/prometeu-lsp-api/src/main/java/p/studio/lsp/LspServiceFactory.java deleted file mode 100644 index 69e6c4f6..00000000 --- a/prometeu-lsp/prometeu-lsp-api/src/main/java/p/studio/lsp/LspServiceFactory.java +++ /dev/null @@ -1,8 +0,0 @@ -package p.studio.lsp; - -import p.studio.lsp.messages.LspProjectContext; -import p.studio.vfs.VfsProjectDocument; - -public interface LspServiceFactory { - LspService open(LspProjectContext projectContext, VfsProjectDocument vfsProjectDocument); -} diff --git a/prometeu-lsp/prometeu-lsp-api/src/main/java/p/studio/lsp/dtos/LspDefinitionTargetDTO.java b/prometeu-lsp/prometeu-lsp-api/src/main/java/p/studio/lsp/dtos/LspDefinitionTargetDTO.java deleted file mode 100644 index 3eadeee4..00000000 --- a/prometeu-lsp/prometeu-lsp-api/src/main/java/p/studio/lsp/dtos/LspDefinitionTargetDTO.java +++ /dev/null @@ -1,16 +0,0 @@ -package p.studio.lsp.dtos; - -import java.nio.file.Path; -import java.util.Objects; - -public record LspDefinitionTargetDTO( - String name, - Path documentPath, - LspRangeDTO range) { - - public LspDefinitionTargetDTO { - name = Objects.requireNonNull(name, "name"); - documentPath = Objects.requireNonNull(documentPath, "documentPath").toAbsolutePath().normalize(); - range = Objects.requireNonNull(range, "range"); - } -} diff --git a/prometeu-lsp/prometeu-lsp-api/src/main/java/p/studio/lsp/dtos/LspDiagnosticDTO.java b/prometeu-lsp/prometeu-lsp-api/src/main/java/p/studio/lsp/dtos/LspDiagnosticDTO.java deleted file mode 100644 index 3eb485e1..00000000 --- a/prometeu-lsp/prometeu-lsp-api/src/main/java/p/studio/lsp/dtos/LspDiagnosticDTO.java +++ /dev/null @@ -1,24 +0,0 @@ -package p.studio.lsp.dtos; - -import p.studio.lsp.messages.LspDiagnosticSeverity; - -import java.nio.file.Path; -import java.util.Objects; - -public record LspDiagnosticDTO( - Path documentPath, - LspRangeDTO range, - LspDiagnosticSeverity severity, - String phase, - String code, - String message) { - - public LspDiagnosticDTO { - documentPath = Objects.requireNonNull(documentPath, "documentPath").toAbsolutePath().normalize(); - range = Objects.requireNonNull(range, "range"); - severity = Objects.requireNonNull(severity, "severity"); - phase = phase == null ? "" : phase; - code = code == null ? "" : code; - message = Objects.requireNonNull(message, "message"); - } -} diff --git a/prometeu-lsp/prometeu-lsp-api/src/main/java/p/studio/lsp/dtos/LspHighlightSpanDTO.java b/prometeu-lsp/prometeu-lsp-api/src/main/java/p/studio/lsp/dtos/LspHighlightSpanDTO.java deleted file mode 100644 index d0b01e3b..00000000 --- a/prometeu-lsp/prometeu-lsp-api/src/main/java/p/studio/lsp/dtos/LspHighlightSpanDTO.java +++ /dev/null @@ -1,13 +0,0 @@ -package p.studio.lsp.dtos; - -import java.util.Objects; - -public record LspHighlightSpanDTO( - LspRangeDTO range, - String semanticKey) { - - public LspHighlightSpanDTO { - range = Objects.requireNonNull(range, "range"); - semanticKey = Objects.requireNonNull(semanticKey, "semanticKey"); - } -} diff --git a/prometeu-lsp/prometeu-lsp-api/src/main/java/p/studio/lsp/dtos/LspInlineHintDTO.java b/prometeu-lsp/prometeu-lsp-api/src/main/java/p/studio/lsp/dtos/LspInlineHintDTO.java deleted file mode 100644 index 44e170f8..00000000 --- a/prometeu-lsp/prometeu-lsp-api/src/main/java/p/studio/lsp/dtos/LspInlineHintDTO.java +++ /dev/null @@ -1,18 +0,0 @@ -package p.studio.lsp.dtos; - -import java.util.Objects; - -public record LspInlineHintDTO( - LspRangeDTO anchor, - String label, - String category) { - - public LspInlineHintDTO { - anchor = Objects.requireNonNull(anchor, "anchor"); - label = Objects.requireNonNull(label, "label").trim(); - category = Objects.requireNonNull(category, "category").trim(); - if (label.isBlank()) { - throw new IllegalArgumentException("label cannot be blank"); - } - } -} diff --git a/prometeu-lsp/prometeu-lsp-api/src/main/java/p/studio/lsp/dtos/LspRangeDTO.java b/prometeu-lsp/prometeu-lsp-api/src/main/java/p/studio/lsp/dtos/LspRangeDTO.java deleted file mode 100644 index 108af2bd..00000000 --- a/prometeu-lsp/prometeu-lsp-api/src/main/java/p/studio/lsp/dtos/LspRangeDTO.java +++ /dev/null @@ -1,15 +0,0 @@ -package p.studio.lsp.dtos; - -public record LspRangeDTO( - int startOffset, - int endOffset) { - - public LspRangeDTO { - startOffset = Math.max(0, startOffset); - endOffset = Math.max(startOffset, endOffset); - } - - public boolean contains(final int offset) { - return startOffset <= offset && offset < endOffset; - } -} diff --git a/prometeu-lsp/prometeu-lsp-api/src/main/java/p/studio/lsp/dtos/LspSemanticPresentationDTO.java b/prometeu-lsp/prometeu-lsp-api/src/main/java/p/studio/lsp/dtos/LspSemanticPresentationDTO.java deleted file mode 100644 index d31eaf88..00000000 --- a/prometeu-lsp/prometeu-lsp-api/src/main/java/p/studio/lsp/dtos/LspSemanticPresentationDTO.java +++ /dev/null @@ -1,14 +0,0 @@ -package p.studio.lsp.dtos; - -import java.util.List; -import java.util.Objects; - -public record LspSemanticPresentationDTO( - List semanticKeys, - List resources) { - - public LspSemanticPresentationDTO { - semanticKeys = List.copyOf(Objects.requireNonNull(semanticKeys, "semanticKeys")); - resources = List.copyOf(Objects.requireNonNull(resources, "resources")); - } -} diff --git a/prometeu-lsp/prometeu-lsp-api/src/main/java/p/studio/lsp/dtos/LspSessionStateDTO.java b/prometeu-lsp/prometeu-lsp-api/src/main/java/p/studio/lsp/dtos/LspSessionStateDTO.java deleted file mode 100644 index 91e758b7..00000000 --- a/prometeu-lsp/prometeu-lsp-api/src/main/java/p/studio/lsp/dtos/LspSessionStateDTO.java +++ /dev/null @@ -1,13 +0,0 @@ -package p.studio.lsp.dtos; - -import java.util.List; -import java.util.Objects; - -public record LspSessionStateDTO( - boolean semanticReadReady, - List declaredCapabilities) { - - public LspSessionStateDTO { - declaredCapabilities = List.copyOf(Objects.requireNonNull(declaredCapabilities, "declaredCapabilities")); - } -} diff --git a/prometeu-lsp/prometeu-lsp-api/src/main/java/p/studio/lsp/dtos/LspStructuralAnchorDTO.java b/prometeu-lsp/prometeu-lsp-api/src/main/java/p/studio/lsp/dtos/LspStructuralAnchorDTO.java deleted file mode 100644 index 334f6f8b..00000000 --- a/prometeu-lsp/prometeu-lsp-api/src/main/java/p/studio/lsp/dtos/LspStructuralAnchorDTO.java +++ /dev/null @@ -1,18 +0,0 @@ -package p.studio.lsp.dtos; - -import java.util.List; -import java.util.Objects; - -public record LspStructuralAnchorDTO( - LspRangeDTO range, - LspRangeDTO startAnchor, - LspRangeDTO endAnchor, - List children) { - - public LspStructuralAnchorDTO { - range = Objects.requireNonNull(range, "range"); - startAnchor = Objects.requireNonNull(startAnchor, "startAnchor"); - endAnchor = Objects.requireNonNull(endAnchor, "endAnchor"); - children = List.copyOf(Objects.requireNonNull(children, "children")); - } -} diff --git a/prometeu-lsp/prometeu-lsp-api/src/main/java/p/studio/lsp/dtos/LspSymbolDTO.java b/prometeu-lsp/prometeu-lsp-api/src/main/java/p/studio/lsp/dtos/LspSymbolDTO.java deleted file mode 100644 index 124b69a0..00000000 --- a/prometeu-lsp/prometeu-lsp-api/src/main/java/p/studio/lsp/dtos/LspSymbolDTO.java +++ /dev/null @@ -1,23 +0,0 @@ -package p.studio.lsp.dtos; - -import p.studio.lsp.messages.LspSymbolKind; - -import java.nio.file.Path; -import java.util.List; -import java.util.Objects; - -public record LspSymbolDTO( - String name, - LspSymbolKind kind, - Path documentPath, - LspRangeDTO range, - List children) { - - public LspSymbolDTO { - name = Objects.requireNonNull(name, "name"); - kind = Objects.requireNonNull(kind, "kind"); - documentPath = Objects.requireNonNull(documentPath, "documentPath").toAbsolutePath().normalize(); - range = Objects.requireNonNull(range, "range"); - children = List.copyOf(Objects.requireNonNull(children, "children")); - } -} diff --git a/prometeu-lsp/prometeu-lsp-api/src/main/java/p/studio/lsp/events/LspEvent.java b/prometeu-lsp/prometeu-lsp-api/src/main/java/p/studio/lsp/events/LspEvent.java deleted file mode 100644 index 7a218128..00000000 --- a/prometeu-lsp/prometeu-lsp-api/src/main/java/p/studio/lsp/events/LspEvent.java +++ /dev/null @@ -1,13 +0,0 @@ -package p.studio.lsp.events; - -import java.util.Objects; - -public record LspEvent( - LspEventKind kind, - String message) { - - public LspEvent { - Objects.requireNonNull(kind, "kind"); - Objects.requireNonNull(message, "message"); - } -} diff --git a/prometeu-lsp/prometeu-lsp-api/src/main/java/p/studio/lsp/events/LspEventKind.java b/prometeu-lsp/prometeu-lsp-api/src/main/java/p/studio/lsp/events/LspEventKind.java deleted file mode 100644 index 94afdb08..00000000 --- a/prometeu-lsp/prometeu-lsp-api/src/main/java/p/studio/lsp/events/LspEventKind.java +++ /dev/null @@ -1,5 +0,0 @@ -package p.studio.lsp.events; - -public enum LspEventKind { - SESSION_READY -} diff --git a/prometeu-lsp/prometeu-lsp-api/src/main/java/p/studio/lsp/events/LspEventSink.java b/prometeu-lsp/prometeu-lsp-api/src/main/java/p/studio/lsp/events/LspEventSink.java deleted file mode 100644 index eca8e3c5..00000000 --- a/prometeu-lsp/prometeu-lsp-api/src/main/java/p/studio/lsp/events/LspEventSink.java +++ /dev/null @@ -1,5 +0,0 @@ -package p.studio.lsp.events; - -public interface LspEventSink { - void publish(LspEvent event); -} diff --git a/prometeu-lsp/prometeu-lsp-api/src/main/java/p/studio/lsp/messages/LspAnalyzeDocumentRequest.java b/prometeu-lsp/prometeu-lsp-api/src/main/java/p/studio/lsp/messages/LspAnalyzeDocumentRequest.java deleted file mode 100644 index c5d3c5d2..00000000 --- a/prometeu-lsp/prometeu-lsp-api/src/main/java/p/studio/lsp/messages/LspAnalyzeDocumentRequest.java +++ /dev/null @@ -1,12 +0,0 @@ -package p.studio.lsp.messages; - -import java.nio.file.Path; -import java.util.Objects; - -public record LspAnalyzeDocumentRequest( - Path documentPath) { - - public LspAnalyzeDocumentRequest { - documentPath = Objects.requireNonNull(documentPath, "documentPath").toAbsolutePath().normalize(); - } -} diff --git a/prometeu-lsp/prometeu-lsp-api/src/main/java/p/studio/lsp/messages/LspAnalyzeDocumentResult.java b/prometeu-lsp/prometeu-lsp-api/src/main/java/p/studio/lsp/messages/LspAnalyzeDocumentResult.java deleted file mode 100644 index 5c647e80..00000000 --- a/prometeu-lsp/prometeu-lsp-api/src/main/java/p/studio/lsp/messages/LspAnalyzeDocumentResult.java +++ /dev/null @@ -1,34 +0,0 @@ -package p.studio.lsp.messages; - -import p.studio.lsp.dtos.LspDiagnosticDTO; -import p.studio.lsp.dtos.LspHighlightSpanDTO; -import p.studio.lsp.dtos.LspInlineHintDTO; -import p.studio.lsp.dtos.LspSemanticPresentationDTO; -import p.studio.lsp.dtos.LspSessionStateDTO; -import p.studio.lsp.dtos.LspStructuralAnchorDTO; -import p.studio.lsp.dtos.LspSymbolDTO; - -import java.util.List; -import java.util.Objects; - -public record LspAnalyzeDocumentResult( - LspSessionStateDTO sessionState, - LspSemanticPresentationDTO semanticPresentation, - List diagnostics, - List semanticHighlights, - List inlineHints, - List documentSymbols, - List structuralAnchors, - List workspaceSymbols) { - - public LspAnalyzeDocumentResult { - Objects.requireNonNull(sessionState, "sessionState"); - Objects.requireNonNull(semanticPresentation, "semanticPresentation"); - diagnostics = List.copyOf(Objects.requireNonNull(diagnostics, "diagnostics")); - semanticHighlights = List.copyOf(Objects.requireNonNull(semanticHighlights, "semanticHighlights")); - inlineHints = List.copyOf(Objects.requireNonNull(inlineHints, "inlineHints")); - documentSymbols = List.copyOf(Objects.requireNonNull(documentSymbols, "documentSymbols")); - structuralAnchors = List.copyOf(Objects.requireNonNull(structuralAnchors, "structuralAnchors")); - workspaceSymbols = List.copyOf(Objects.requireNonNull(workspaceSymbols, "workspaceSymbols")); - } -} diff --git a/prometeu-lsp/prometeu-lsp-api/src/main/java/p/studio/lsp/messages/LspDefinitionRequest.java b/prometeu-lsp/prometeu-lsp-api/src/main/java/p/studio/lsp/messages/LspDefinitionRequest.java deleted file mode 100644 index af205092..00000000 --- a/prometeu-lsp/prometeu-lsp-api/src/main/java/p/studio/lsp/messages/LspDefinitionRequest.java +++ /dev/null @@ -1,14 +0,0 @@ -package p.studio.lsp.messages; - -import java.nio.file.Path; -import java.util.Objects; - -public record LspDefinitionRequest( - Path documentPath, - int offset) { - - public LspDefinitionRequest { - documentPath = Objects.requireNonNull(documentPath, "documentPath").toAbsolutePath().normalize(); - offset = Math.max(0, offset); - } -} diff --git a/prometeu-lsp/prometeu-lsp-api/src/main/java/p/studio/lsp/messages/LspDefinitionResult.java b/prometeu-lsp/prometeu-lsp-api/src/main/java/p/studio/lsp/messages/LspDefinitionResult.java deleted file mode 100644 index 8067702c..00000000 --- a/prometeu-lsp/prometeu-lsp-api/src/main/java/p/studio/lsp/messages/LspDefinitionResult.java +++ /dev/null @@ -1,19 +0,0 @@ -package p.studio.lsp.messages; - -import p.studio.lsp.dtos.LspDefinitionTargetDTO; - -import java.nio.file.Path; -import java.util.List; -import java.util.Objects; - -public record LspDefinitionResult( - Path documentPath, - int offset, - List targets) { - - public LspDefinitionResult { - documentPath = Objects.requireNonNull(documentPath, "documentPath").toAbsolutePath().normalize(); - offset = Math.max(0, offset); - targets = List.copyOf(Objects.requireNonNull(targets, "targets")); - } -} diff --git a/prometeu-lsp/prometeu-lsp-api/src/main/java/p/studio/lsp/messages/LspDiagnosticSeverity.java b/prometeu-lsp/prometeu-lsp-api/src/main/java/p/studio/lsp/messages/LspDiagnosticSeverity.java deleted file mode 100644 index 2481f6b1..00000000 --- a/prometeu-lsp/prometeu-lsp-api/src/main/java/p/studio/lsp/messages/LspDiagnosticSeverity.java +++ /dev/null @@ -1,6 +0,0 @@ -package p.studio.lsp.messages; - -public enum LspDiagnosticSeverity { - ERROR, - WARNING -} diff --git a/prometeu-lsp/prometeu-lsp-api/src/main/java/p/studio/lsp/messages/LspProjectContext.java b/prometeu-lsp/prometeu-lsp-api/src/main/java/p/studio/lsp/messages/LspProjectContext.java deleted file mode 100644 index 85b44151..00000000 --- a/prometeu-lsp/prometeu-lsp-api/src/main/java/p/studio/lsp/messages/LspProjectContext.java +++ /dev/null @@ -1,16 +0,0 @@ -package p.studio.lsp.messages; - -import java.nio.file.Path; -import java.util.Objects; - -public record LspProjectContext( - String projectName, - String languageId, - Path rootPath) { - - public LspProjectContext { - Objects.requireNonNull(projectName, "projectName"); - Objects.requireNonNull(languageId, "languageId"); - rootPath = Objects.requireNonNull(rootPath, "rootPath").toAbsolutePath().normalize(); - } -} diff --git a/prometeu-lsp/prometeu-lsp-api/src/main/java/p/studio/lsp/messages/LspSymbolKind.java b/prometeu-lsp/prometeu-lsp-api/src/main/java/p/studio/lsp/messages/LspSymbolKind.java deleted file mode 100644 index 3f65c287..00000000 --- a/prometeu-lsp/prometeu-lsp-api/src/main/java/p/studio/lsp/messages/LspSymbolKind.java +++ /dev/null @@ -1,24 +0,0 @@ -package p.studio.lsp.messages; - -public enum LspSymbolKind { - FUNCTION, - METHOD, - CONSTRUCTOR, - IF, - SWITCH, - FOR, - WHILE, - HANDLE, - GLOBAL, - CONST, - STRUCT, - CONTRACT, - HOST, - BUILTIN_TYPE, - SERVICE, - ERROR, - ENUM, - CALLBACK, - IMPLEMENTS, - UNKNOWN -} diff --git a/prometeu-lsp/prometeu-lsp-api/src/test/java/p/studio/lsp/dtos/LspInlineHintDTOTest.java b/prometeu-lsp/prometeu-lsp-api/src/test/java/p/studio/lsp/dtos/LspInlineHintDTOTest.java deleted file mode 100644 index f4489a17..00000000 --- a/prometeu-lsp/prometeu-lsp-api/src/test/java/p/studio/lsp/dtos/LspInlineHintDTOTest.java +++ /dev/null @@ -1,22 +0,0 @@ -package p.studio.lsp.dtos; - -import org.junit.jupiter.api.Test; - -import static org.junit.jupiter.api.Assertions.assertEquals; -import static org.junit.jupiter.api.Assertions.assertThrows; - -final class LspInlineHintDTOTest { - @Test - void trimsLabelAndCategory() { - final var hint = new LspInlineHintDTO(new LspRangeDTO(3, 3), " int ", " type "); - - assertEquals("int", hint.label()); - assertEquals("type", hint.category()); - } - - @Test - void rejectsBlankLabels() { - assertThrows(IllegalArgumentException.class, () -> - new LspInlineHintDTO(new LspRangeDTO(1, 1), " ", "type")); - } -} diff --git a/prometeu-lsp/prometeu-lsp-v1/build.gradle.kts b/prometeu-lsp/prometeu-lsp-v1/build.gradle.kts deleted file mode 100644 index 37704dc3..00000000 --- a/prometeu-lsp/prometeu-lsp-v1/build.gradle.kts +++ /dev/null @@ -1,16 +0,0 @@ -plugins { - id("gradle.java-library-conventions") -} - -dependencies { - implementation(project(":prometeu-lsp:prometeu-lsp-api")) - implementation(project(":prometeu-vfs:prometeu-vfs-api")) - implementation(project(":prometeu-compiler:prometeu-compiler-core")) - implementation(project(":prometeu-compiler:prometeu-frontend-api")) - implementation(project(":prometeu-compiler:prometeu-frontend-registry")) - implementation(project(":prometeu-compiler:prometeu-deps")) - implementation(project(":prometeu-compiler:prometeu-build-pipeline")) - implementation(project(":prometeu-compiler:frontends:prometeu-frontend-pbs")) - - testImplementation(project(":prometeu-vfs:prometeu-vfs-v1")) -} diff --git a/prometeu-lsp/prometeu-lsp-v1/src/main/java/p/studio/lsp/LspSemanticAnalyseService.java b/prometeu-lsp/prometeu-lsp-v1/src/main/java/p/studio/lsp/LspSemanticAnalyseService.java deleted file mode 100644 index 73380dbf..00000000 --- a/prometeu-lsp/prometeu-lsp-v1/src/main/java/p/studio/lsp/LspSemanticAnalyseService.java +++ /dev/null @@ -1,27 +0,0 @@ -package p.studio.lsp; - -import p.studio.lsp.dtos.LspSessionStateDTO; -import p.studio.lsp.messages.LspAnalyzeDocumentRequest; -import p.studio.lsp.messages.LspAnalyzeDocumentResult; -import p.studio.lsp.messages.SemanticSession; - -import java.util.List; - -import static p.studio.lsp.LspSemanticUtilities.normalize; - -class LspSemanticAnalyseService { - LspAnalyzeDocumentResult analyze( - final SemanticSession session, - final LspAnalyzeDocumentRequest request) { - final var normalizedRequestedDocument = normalize(request.documentPath()); - return new LspAnalyzeDocumentResult( - new LspSessionStateDTO(true, List.of("diagnostics", "symbols", "definition", "highlight", "structural-anchors")), - session.semanticPresentation(), - session.diagnosticsByDocument().getOrDefault(normalizedRequestedDocument, List.of()), - session.semanticHighlightsByDocument().getOrDefault(normalizedRequestedDocument, List.of()), - session.inlineHintsByDocument().getOrDefault(normalizedRequestedDocument, List.of()), - session.documentSymbolsByDocument().getOrDefault(normalizedRequestedDocument, List.of()), - session.structuralAnchorsByDocument().getOrDefault(normalizedRequestedDocument, List.of()), - session.workspaceSymbols()); - } -} diff --git a/prometeu-lsp/prometeu-lsp-v1/src/main/java/p/studio/lsp/LspSemanticDefinitionService.java b/prometeu-lsp/prometeu-lsp-v1/src/main/java/p/studio/lsp/LspSemanticDefinitionService.java deleted file mode 100644 index b727c278..00000000 --- a/prometeu-lsp/prometeu-lsp-v1/src/main/java/p/studio/lsp/LspSemanticDefinitionService.java +++ /dev/null @@ -1,46 +0,0 @@ -package p.studio.lsp; - -import p.studio.compiler.pbs.lexer.PbsToken; -import p.studio.compiler.pbs.lexer.PbsTokenKind; -import p.studio.lsp.dtos.LspDefinitionTargetDTO; -import p.studio.lsp.dtos.LspSymbolDTO; -import p.studio.lsp.messages.LspDefinitionRequest; -import p.studio.lsp.messages.LspDefinitionResult; -import p.studio.lsp.messages.SemanticSession; - -import java.nio.file.Path; -import java.util.List; - -import static p.studio.lsp.LspSemanticUtilities.normalize; -import static p.studio.lsp.LspSemanticUtilities.tokenAt; - -class LspSemanticDefinitionService { - - LspDefinitionResult definition( - final SemanticSession session, - final LspDefinitionRequest request) { - final List targets = resolveDefinitionTargets(session, request); - return new LspDefinitionResult(request.documentPath(), request.offset(), targets); - } - - private List resolveDefinitionTargets( - final SemanticSession session, - final LspDefinitionRequest request) { - final Path documentPath = normalize(request.documentPath()); - final List tokens = session.tokensByDocument().getOrDefault(documentPath, List.of()); - final PbsToken activeToken = tokenAt(tokens, request.offset()); - if (activeToken == null || activeToken.kind() != PbsTokenKind.IDENTIFIER) { - return List.of(); - } - final String lexeme = activeToken.lexeme(); - final List sameDocumentMatches = session.symbolsByName().getOrDefault(lexeme, List.of()).stream() - .filter(symbol -> symbol.documentPath().equals(documentPath)) - .toList(); - final List effectiveMatches = sameDocumentMatches.isEmpty() - ? session.symbolsByName().getOrDefault(lexeme, List.of()) - : sameDocumentMatches; - return effectiveMatches.stream() - .map(symbol -> new LspDefinitionTargetDTO(symbol.name(), symbol.documentPath(), symbol.range())) - .toList(); - } -} diff --git a/prometeu-lsp/prometeu-lsp-v1/src/main/java/p/studio/lsp/LspSemanticReadPhase.java b/prometeu-lsp/prometeu-lsp-v1/src/main/java/p/studio/lsp/LspSemanticReadPhase.java deleted file mode 100644 index 0163745c..00000000 --- a/prometeu-lsp/prometeu-lsp-v1/src/main/java/p/studio/lsp/LspSemanticReadPhase.java +++ /dev/null @@ -1,353 +0,0 @@ -package p.studio.lsp; - -import p.studio.compiler.FrontendRegistryService; -import p.studio.compiler.messages.*; -import p.studio.compiler.models.AnalysisSnapshot; -import p.studio.compiler.models.BuilderPipelineContext; -import p.studio.compiler.models.FrontendSpec; -import p.studio.compiler.models.FrontendSemanticPresentationSpec; -import p.studio.compiler.models.SourceHandle; -import p.studio.compiler.pbs.ast.PbsAst; -import p.studio.compiler.pbs.lexer.PbsLexer; -import p.studio.compiler.pbs.parser.PbsParser; -import p.studio.compiler.source.diagnostics.Diagnostic; -import p.studio.compiler.source.diagnostics.DiagnosticSink; -import p.studio.compiler.source.identifiers.FileId; -import p.studio.compiler.services.PBSFrontendPhaseService; -import p.studio.compiler.services.PbsInlineHintSurface; -import p.studio.compiler.workspaces.AssetSurfaceContextLoader; -import p.studio.compiler.workspaces.PipelineStage; -import p.studio.compiler.workspaces.stages.LoadSourcesPipelineStage; -import p.studio.compiler.workspaces.stages.ResolveDepsPipelineStage; -import p.studio.lsp.dtos.LspDiagnosticDTO; -import p.studio.lsp.dtos.LspInlineHintDTO; -import p.studio.lsp.dtos.LspRangeDTO; -import p.studio.lsp.dtos.LspSemanticPresentationDTO; -import p.studio.lsp.messages.*; -import p.studio.lsp.models.AnalysisRuntimeSnapshot; -import p.studio.lsp.models.SemanticIndex; -import p.studio.utilities.logs.LogAggregator; -import p.studio.vfs.VfsProjectDocument; - -import java.nio.file.Path; -import java.util.ArrayList; -import java.util.LinkedHashMap; -import java.util.List; -import java.util.Map; - -import static p.studio.lsp.LspSemanticUtilities.*; - -final class LspSemanticReadPhase { - private final LspSemanticAnalyseService analyseService; - private final LspSemanticDefinitionService definitionService; - - LspSemanticReadPhase() { - this.analyseService = new LspSemanticAnalyseService(); - this.definitionService = new LspSemanticDefinitionService(); - } - - public LspAnalyzeDocumentResult analyze( - final LspProjectContext projectContext, - final VfsProjectDocument vfsProjectDocument, - final LspAnalyzeDocumentRequest request) { - final var session = buildSession(projectContext, vfsProjectDocument, request.documentPath()); - return analyseService.analyze(session, request); - } - - public LspDefinitionResult definition( - final LspProjectContext projectContext, - final VfsProjectDocument vfsProjectDocument, - final LspDefinitionRequest request) { - final var session = buildSession(projectContext, vfsProjectDocument, request.documentPath()); - return definitionService.definition(session, request); - } - - public static SemanticSession buildSession( - final LspProjectContext projectContext, - final VfsProjectDocument vfsProjectDocument, - final Path requestedDocumentPath) { - final BuilderPipelineConfig config = new BuilderPipelineConfig( - false, - projectContext.rootPath().toString(), - "core-v1", - new OverlaySourceProviderFactoryImpl(vfsProjectDocument, requestedDocumentPath)); - final BuilderPipelineContext context = BuilderPipelineContext.fromConfig(config); - final AnalysisRuntimeSnapshot snapshot = runAnalysisStages(context); - return index(snapshot, context, requestedDocumentPath); - } - - private static AnalysisRuntimeSnapshot runAnalysisStages(final BuilderPipelineContext context) { - final LogAggregator logs = LogAggregator.empty(); - final List diagnostics = new ArrayList<>(); - final List stages = List.of( - new ResolveDepsPipelineStage(), - new LoadSourcesPipelineStage()); - for (final PipelineStage stage : stages) { - final BuildingIssueSink stageIssues = stage.run(context, logs); - diagnostics.addAll(stageIssues.asCollection()); - if (stageIssues.hasErrors()) { - break; - } - } - final DiagnosticSink frontendDiagnostics = DiagnosticSink.empty(); - FrontendSpec frontendSpec = FrontendRegistryService.getDefaultFrontendSpec(); - if (context.resolvedWorkspace != null && context.fileTable != null) { - final BuildingIssueSink frontendIssues = runFrontendPhase(context, logs, frontendDiagnostics); - diagnostics.addAll(frontendIssues.asCollection()); - frontendSpec = context.resolvedWorkspace.frontendSpec(); - } - return new AnalysisRuntimeSnapshot( - new AnalysisSnapshot( - frontendSpec, - diagnostics, - context.resolvedWorkspace, - context.fileTable, - context.irBackend), - List.copyOf(frontendDiagnostics.asCollection())); - } - - private static BuildingIssueSink runFrontendPhase( - final BuilderPipelineContext context, - final LogAggregator logs, - final DiagnosticSink frontendDiagnostics) { - final var frontendSpec = context.resolvedWorkspace.frontendSpec(); - final var service = FrontendRegistryService.getFrontendPhaseService(frontendSpec.getLanguageId()); - if (service.isEmpty()) { - return BuildingIssueSink.empty().report(builder -> builder - .error(true) - .message("[BUILD]: unable to find a service for frontend phase: " + frontendSpec.getLanguageId())); - } - final FESurfaceContext feSurfaceContext = new AssetSurfaceContextLoader().load(context.resolvedWorkspace.mainProject().getRootPath()); - final FrontendPhaseContext frontendPhaseContext = new FrontendPhaseContext( - context.resolvedWorkspace.graph().projectTable(), - context.fileTable, - context.resolvedWorkspace.stack(), - context.resolvedWorkspace.stdlib(), - HostAdmissionContext.permissiveDefault(), - feSurfaceContext); - final BuildingIssueSink issues = BuildingIssueSink.empty(); - context.irBackend = service.get().compile(frontendPhaseContext, frontendDiagnostics, logs, issues); - return issues; - } - - private static SemanticSession index( - final AnalysisRuntimeSnapshot runtimeSnapshot, - final BuilderPipelineContext context, - final Path requestedDocumentPath) { - final AnalysisSnapshot snapshot = runtimeSnapshot.analysisSnapshot(); - final Map> diagnosticsByDocument = diagnosticsByDocument( - snapshot.diagnostics(), - snapshot, - runtimeSnapshot.frontendDiagnostics()); - final SemanticIndex semanticIndex = new SemanticIndex(); - if (snapshot.fileTable() == null) { - return new SemanticSession( - normalize(requestedDocumentPath), - semanticPresentation(snapshot.frontendSpec()), - diagnosticsByDocument, - Map.of(), - Map.of(), - Map.of(), - Map.of(), - List.of(), - Map.of(), - Map.of()); - } - final Map> importedSupplementalTopDeclsByFile = importedSupplementalTopDeclsByFile( - snapshot.frontendSpec(), - context); - final Map> inlineHintsByDocument = inlineHintsByDocument( - snapshot, - snapshot.frontendSpec(), - context); - final List indexedDocuments = new ArrayList<>(); - for (final FileId fileId : snapshot.fileTable()) { - final SourceHandle sourceHandle = snapshot.fileTable().get(fileId); - if (!isSourceRelated(snapshot.frontendSpec(), sourceHandle)) { - continue; - } - final String source = sourceHandle.readUtf8().orElse(""); - final DiagnosticSink diagnostics = DiagnosticSink.empty(); - final var tokens = PbsLexer.lex(source, fileId, diagnostics); - final PbsAst.File ast = PbsParser.parse(tokens, fileId, diagnostics, PbsParser.ParseMode.ORDINARY); - final Path documentPath = sourceHandle.getCanonPath(); - semanticIndex.registerDocument(documentPath, ast, tokens.asList()); - indexedDocuments.add(new IndexedDocument( - fileId, - documentPath, - importedSupplementalTopDeclsByFile.getOrDefault(fileId, List.of()))); - } - for (final IndexedDocument indexedDocument : indexedDocuments) { - semanticIndex.buildHighlights( - indexedDocument.documentPath(), - indexedDocument.visibleImportedTopDecls()); - } - return new SemanticSession( - normalize(requestedDocumentPath), - semanticPresentation(snapshot.frontendSpec()), - diagnosticsByDocument, - semanticIndex.semanticHighlightsByDocument(), - inlineHintsByDocument, - semanticIndex.documentSymbolsByDocument(), - semanticIndex.structuralAnchorsByDocument(), - semanticIndex.workspaceSymbols(), - semanticIndex.symbolsByName(), - semanticIndex.tokensByDocument()); - } - - private static Map> importedSupplementalTopDeclsByFile( - final FrontendSpec frontendSpec, - final BuilderPipelineContext context) { - final var surface = semanticReadSurface(frontendSpec, context); - final Map> byFile = new LinkedHashMap<>(); - for (final var entry : surface.supplementalTopDeclsByFile().entrySet()) { - byFile.put(entry.getKey(), entry.getValue().asList()); - } - return Map.copyOf(byFile); - } - - private static Map> inlineHintsByDocument( - final AnalysisSnapshot snapshot, - final FrontendSpec frontendSpec, - final BuilderPipelineContext context) { - if (snapshot.fileTable() == null) { - return Map.of(); - } - final var surface = semanticReadSurface(frontendSpec, context); - final Map> byDocument = new LinkedHashMap<>(); - for (final var entry : surface.inlineHintsByFile().entrySet()) { - final SourceHandle sourceHandle = snapshot.fileTable().get(entry.getKey()); - final Path documentPath = sourceHandle.getCanonPath().toAbsolutePath().normalize(); - final var hints = entry.getValue().asList().stream() - .map(LspSemanticReadPhase::toInlineHintDTO) - .toList(); - if (!hints.isEmpty()) { - byDocument.put(documentPath, hints); - } - } - return Map.copyOf(byDocument); - } - - private static PBSFrontendPhaseService.PbsSemanticReadSurface semanticReadSurface( - final FrontendSpec frontendSpec, - final BuilderPipelineContext context) { - if (context.resolvedWorkspace == null || context.fileTable == null || !"pbs".equals(frontendSpec.getLanguageId())) { - return new PBSFrontendPhaseService.PbsSemanticReadSurface(Map.of(), Map.of()); - } - final FESurfaceContext feSurfaceContext = new AssetSurfaceContextLoader().load(context.resolvedWorkspace.mainProject().getRootPath()); - final FrontendPhaseContext frontendPhaseContext = new FrontendPhaseContext( - context.resolvedWorkspace.graph().projectTable(), - context.fileTable, - context.resolvedWorkspace.stack(), - context.resolvedWorkspace.stdlib(), - HostAdmissionContext.permissiveDefault(), - feSurfaceContext); - final var diagnostics = DiagnosticSink.empty(); - final var issues = BuildingIssueSink.empty(); - return PBSFrontendPhaseService.semanticReadSurface( - frontendPhaseContext, - diagnostics, - issues); - } - - private static LspInlineHintDTO toInlineHintDTO(final PbsInlineHintSurface hint) { - return new LspInlineHintDTO( - new LspRangeDTO( - (int) hint.anchorSpan().getStart(), - (int) hint.anchorSpan().getEnd()), - hint.label(), - hint.category()); - } - - private record IndexedDocument( - FileId fileId, - Path documentPath, - List visibleImportedTopDecls) { - } - - private static boolean isSourceRelated(final FrontendSpec frontendSpec, final SourceHandle sourceHandle) { - return frontendSpec.getAllowedExtensions().contains(sourceHandle.getExtension()); - } - - private static LspSemanticPresentationDTO semanticPresentation(final FrontendSpec frontendSpec) { - final FrontendSemanticPresentationSpec presentation = frontendSpec.getSemanticPresentation(); - return new LspSemanticPresentationDTO(presentation.semanticKeys(), presentation.resources()); - } - - private static Map> diagnosticsByDocument( - final List issues, - final AnalysisSnapshot snapshot, - final List frontendDiagnostics) { - final Map> diagnosticsByDocument = new LinkedHashMap<>(); - diagnosticIssues(issues, snapshot, diagnosticsByDocument); - diagnosticFrontend(frontendDiagnostics, snapshot, diagnosticsByDocument); - return freezeMapOfLists(diagnosticsByDocument); - } - - private static boolean isValidIssueDiagnostic( - final AnalysisSnapshot snapshot, - final BuildingIssue issue) { - if (snapshot.fileTable() == null || issue.getFileId() == null || issue.getFileId() < 0) { - return false; - } - return issue.getFileId() < snapshot.fileTable().size(); - } - - private static void diagnosticIssues( - final List issues, - final AnalysisSnapshot snapshot, - final Map> diagnosticsByDocument) { - for (final var issue : issues) { - if (!isValidIssueDiagnostic(snapshot, issue)) { - continue; - } - final SourceHandle sourceHandle = snapshot.fileTable().get(new FileId(issue.getFileId())); - final Path documentPath = sourceHandle.getCanonPath().toAbsolutePath().normalize(); - diagnosticsByDocument - .computeIfAbsent(documentPath, ignored -> new ArrayList<>()) - .add(new LspDiagnosticDTO( - documentPath, - new LspRangeDTO( - safeOffset(issue.getStart()), - safeEnd(issue.getStart(), issue.getEnd())), - issue.isError() - ? LspDiagnosticSeverity.ERROR - : LspDiagnosticSeverity.WARNING, - issue.getPhase(), - issue.getCode(), - issue.getMessage())); - } - } - - private static boolean isValidFEDiagnostic( - final AnalysisSnapshot snapshot, - final Diagnostic diagnostic) { - return snapshot.fileTable() != null && !diagnostic.getSpan().getFileId().isNone(); - } - - private static void diagnosticFrontend( - final List feDiagnostics, - final AnalysisSnapshot snapshot, - final Map> diagnosticsByDocument) { - for (final var feDiagnostic : feDiagnostics) { - if (!isValidFEDiagnostic(snapshot, feDiagnostic)) { - continue; - } - final SourceHandle sourceHandle = snapshot.fileTable().get(feDiagnostic.getSpan().getFileId()); - final Path documentPath = sourceHandle.getCanonPath().toAbsolutePath().normalize(); - diagnosticsByDocument - .computeIfAbsent(documentPath, ignored -> new ArrayList<>()) - .add(new LspDiagnosticDTO( - documentPath, - new LspRangeDTO( - (int) feDiagnostic.getSpan().getStart(), - (int) feDiagnostic.getSpan().getEnd()), - feDiagnostic.getSeverity().isError() - ? LspDiagnosticSeverity.ERROR - : LspDiagnosticSeverity.WARNING, - feDiagnostic.getPhase().name(), - feDiagnostic.getCode(), - feDiagnostic.getMessage())); - } - } -} diff --git a/prometeu-lsp/prometeu-lsp-v1/src/main/java/p/studio/lsp/LspSemanticUtilities.java b/prometeu-lsp/prometeu-lsp-v1/src/main/java/p/studio/lsp/LspSemanticUtilities.java deleted file mode 100644 index b3894df1..00000000 --- a/prometeu-lsp/prometeu-lsp-v1/src/main/java/p/studio/lsp/LspSemanticUtilities.java +++ /dev/null @@ -1,52 +0,0 @@ -package p.studio.lsp; - -import lombok.experimental.UtilityClass; -import p.studio.compiler.pbs.lexer.PbsToken; - -import java.io.IOException; -import java.nio.file.Files; -import java.nio.file.Path; -import java.util.LinkedHashMap; -import java.util.List; -import java.util.Map; -import java.util.Objects; - -@UtilityClass -public class LspSemanticUtilities { - - public static PbsToken tokenAt(final List tokens, final int offset) { - for (final PbsToken token : tokens) { - if (token.start() <= offset && offset < token.end()) { - return token; - } - } - return null; - } - - public static Path normalize(final Path path) { - final Path normalized = Objects.requireNonNull(path, "path").toAbsolutePath().normalize(); - try { - return Files.exists(normalized) ? normalized.toRealPath() : normalized; - } catch (IOException ignored) { - return normalized; - } - } - - public static Map> freezeMapOfLists(final Map> mutable) { - final Map> frozen = new LinkedHashMap<>(); - for (final var entry : mutable.entrySet()) { - frozen.put(entry.getKey(), List.copyOf(entry.getValue())); - } - return Map.copyOf(frozen); - } - - public static int safeOffset(final Integer value) { - return value == null ? 0 : Math.max(0, value); - } - - public static int safeEnd(final Integer start, final Integer end) { - final int safeStart = safeOffset(start); - final int safeEnd = safeOffset(end); - return Math.max(safeStart, safeEnd); - } -} diff --git a/prometeu-lsp/prometeu-lsp-v1/src/main/java/p/studio/lsp/LspServiceFactoryImpl.java b/prometeu-lsp/prometeu-lsp-v1/src/main/java/p/studio/lsp/LspServiceFactoryImpl.java deleted file mode 100644 index 79abcb93..00000000 --- a/prometeu-lsp/prometeu-lsp-v1/src/main/java/p/studio/lsp/LspServiceFactoryImpl.java +++ /dev/null @@ -1,17 +0,0 @@ -package p.studio.lsp; - -import p.studio.lsp.messages.LspProjectContext; -import p.studio.vfs.VfsProjectDocument; - -import java.util.Objects; - -public final class LspServiceFactoryImpl implements LspServiceFactory { - @Override - public LspService open( - final LspProjectContext projectContext, - final VfsProjectDocument vfsProjectDocument) { - return new LspServiceImpl( - Objects.requireNonNull(projectContext, "projectContext"), - Objects.requireNonNull(vfsProjectDocument, "vfsProjectDocument")); - } -} diff --git a/prometeu-lsp/prometeu-lsp-v1/src/main/java/p/studio/lsp/LspServiceImpl.java b/prometeu-lsp/prometeu-lsp-v1/src/main/java/p/studio/lsp/LspServiceImpl.java deleted file mode 100644 index e85596c3..00000000 --- a/prometeu-lsp/prometeu-lsp-v1/src/main/java/p/studio/lsp/LspServiceImpl.java +++ /dev/null @@ -1,50 +0,0 @@ -package p.studio.lsp; - -import p.studio.lsp.dtos.LspSessionStateDTO; -import p.studio.lsp.messages.*; -import p.studio.vfs.VfsProjectDocument; - -import java.util.List; -import java.util.Objects; - -public final class LspServiceImpl implements LspService { - private final LspProjectContext projectContext; - private final VfsProjectDocument vfsProjectDocument; - - private final LspSemanticReadPhase semanticReadPhase; - - public LspServiceImpl( - final LspProjectContext projectContext, - final VfsProjectDocument vfsProjectDocument) { - this.projectContext = Objects.requireNonNull(projectContext, "projectContext"); - this.vfsProjectDocument = Objects.requireNonNull(vfsProjectDocument, "vfsProjectDocument"); - this.semanticReadPhase = new LspSemanticReadPhase(); - } - - @Override - public LspProjectContext projectContext() { - return projectContext; - } - - @Override - public VfsProjectDocument projectDocumentVfs() { - return vfsProjectDocument; - } - - @Override - public LspSessionStateDTO snapshot() { - return new LspSessionStateDTO( - true, - List.of("diagnostics", "symbols", "definition", "highlight")); - } - - @Override - public LspAnalyzeDocumentResult analyzeDocument(final LspAnalyzeDocumentRequest request) { - return semanticReadPhase.analyze(projectContext, vfsProjectDocument, request); - } - - @Override - public LspDefinitionResult definition(final LspDefinitionRequest request) { - return semanticReadPhase.definition(projectContext, vfsProjectDocument, request); - } -} diff --git a/prometeu-lsp/prometeu-lsp-v1/src/main/java/p/studio/lsp/OverlaySourceProviderFactoryImpl.java b/prometeu-lsp/prometeu-lsp-v1/src/main/java/p/studio/lsp/OverlaySourceProviderFactoryImpl.java deleted file mode 100644 index e6ef0ac3..00000000 --- a/prometeu-lsp/prometeu-lsp-v1/src/main/java/p/studio/lsp/OverlaySourceProviderFactoryImpl.java +++ /dev/null @@ -1,51 +0,0 @@ -package p.studio.lsp; - -import p.studio.compiler.utilities.SourceProvider; -import p.studio.compiler.utilities.SourceProviderFactory; -import p.studio.vfs.VfsDocumentOpenResult; -import p.studio.vfs.VfsProjectDocument; - -import java.io.IOException; -import java.nio.charset.StandardCharsets; -import java.nio.file.Files; -import java.nio.file.Path; -import java.util.Objects; - -final class OverlaySourceProviderFactoryImpl implements SourceProviderFactory { - private final VfsProjectDocument vfsProjectDocument; - private final Path openedDocumentPath; - - OverlaySourceProviderFactoryImpl( - final VfsProjectDocument vfsProjectDocument, - final Path openedDocumentPath) { - this.vfsProjectDocument = Objects.requireNonNull(vfsProjectDocument, "vfsProjectDocument"); - this.openedDocumentPath = openedDocumentPath == null - ? null - : normalize(openedDocumentPath); - } - - @Override - public SourceProvider create(final Path path) { - final Path normalizedPath = normalize(path); - return () -> read(normalizedPath); - } - - private byte[] read(final Path path) throws IOException { - if (openedDocumentPath != null && openedDocumentPath.equals(path)) { - final VfsDocumentOpenResult result = vfsProjectDocument.openDocument(path); - if (result instanceof VfsDocumentOpenResult.VfsTextDocument textDocument) { - return textDocument.content().getBytes(StandardCharsets.UTF_8); - } - } - return Files.readAllBytes(path); - } - - private Path normalize(final Path path) { - final Path normalized = path.toAbsolutePath().normalize(); - try { - return Files.exists(normalized) ? normalized.toRealPath() : normalized; - } catch (IOException ignored) { - return normalized; - } - } -} diff --git a/prometeu-lsp/prometeu-lsp-v1/src/main/java/p/studio/lsp/messages/SemanticSession.java b/prometeu-lsp/prometeu-lsp-v1/src/main/java/p/studio/lsp/messages/SemanticSession.java deleted file mode 100644 index 3d3f23f9..00000000 --- a/prometeu-lsp/prometeu-lsp-v1/src/main/java/p/studio/lsp/messages/SemanticSession.java +++ /dev/null @@ -1,26 +0,0 @@ -package p.studio.lsp.messages; - -import p.studio.compiler.pbs.lexer.PbsToken; -import p.studio.lsp.dtos.LspDiagnosticDTO; -import p.studio.lsp.dtos.LspHighlightSpanDTO; -import p.studio.lsp.dtos.LspInlineHintDTO; -import p.studio.lsp.dtos.LspSemanticPresentationDTO; -import p.studio.lsp.dtos.LspStructuralAnchorDTO; -import p.studio.lsp.dtos.LspSymbolDTO; - -import java.nio.file.Path; -import java.util.List; -import java.util.Map; - -public record SemanticSession( - Path requestedDocumentPath, - LspSemanticPresentationDTO semanticPresentation, - Map> diagnosticsByDocument, - Map> semanticHighlightsByDocument, - Map> inlineHintsByDocument, - Map> documentSymbolsByDocument, - Map> structuralAnchorsByDocument, - List workspaceSymbols, - Map> symbolsByName, - Map> tokensByDocument) { -} diff --git a/prometeu-lsp/prometeu-lsp-v1/src/main/java/p/studio/lsp/models/AnalysisRuntimeSnapshot.java b/prometeu-lsp/prometeu-lsp-v1/src/main/java/p/studio/lsp/models/AnalysisRuntimeSnapshot.java deleted file mode 100644 index 65a6e234..00000000 --- a/prometeu-lsp/prometeu-lsp-v1/src/main/java/p/studio/lsp/models/AnalysisRuntimeSnapshot.java +++ /dev/null @@ -1,11 +0,0 @@ -package p.studio.lsp.models; - -import p.studio.compiler.models.AnalysisSnapshot; -import p.studio.compiler.source.diagnostics.Diagnostic; - -import java.util.List; - -public record AnalysisRuntimeSnapshot( - AnalysisSnapshot analysisSnapshot, - List frontendDiagnostics) { -} \ No newline at end of file diff --git a/prometeu-lsp/prometeu-lsp-v1/src/main/java/p/studio/lsp/models/SemanticIndex.java b/prometeu-lsp/prometeu-lsp-v1/src/main/java/p/studio/lsp/models/SemanticIndex.java deleted file mode 100644 index 1649d505..00000000 --- a/prometeu-lsp/prometeu-lsp-v1/src/main/java/p/studio/lsp/models/SemanticIndex.java +++ /dev/null @@ -1,635 +0,0 @@ -package p.studio.lsp.models; - -import p.studio.compiler.pbs.PbsSemanticKind; -import p.studio.compiler.pbs.ast.PbsAst; -import p.studio.compiler.pbs.lexer.PbsToken; -import p.studio.compiler.pbs.lexer.PbsTokenKind; -import p.studio.compiler.source.Span; -import p.studio.lsp.dtos.LspHighlightSpanDTO; -import p.studio.lsp.dtos.LspRangeDTO; -import p.studio.lsp.dtos.LspStructuralAnchorDTO; -import p.studio.lsp.dtos.LspSymbolDTO; -import p.studio.lsp.messages.LspSymbolKind; - -import java.nio.file.Path; -import java.util.ArrayList; -import java.util.LinkedHashMap; -import java.util.List; -import java.util.Map; -import java.util.Objects; - -import static p.studio.lsp.LspSemanticUtilities.normalize; - -public final class SemanticIndex { - private final Map> semanticHighlightsByDocument = new LinkedHashMap<>(); - private final Map> documentSymbolsByDocument = new LinkedHashMap<>(); - private final Map> structuralAnchorsByDocument = new LinkedHashMap<>(); - private final List workspaceSymbols = new ArrayList<>(); - private final Map> symbolsByName = new LinkedHashMap<>(); - private final Map> tokensByDocument = new LinkedHashMap<>(); - - public void index( - final Path documentPath, - final PbsAst.File ast, - final List tokens) { - index(documentPath, ast, tokens, List.of()); - } - - public void index( - final Path documentPath, - final PbsAst.File ast, - final List tokens, - final List visibleImportedTopDecls) { - registerDocument(documentPath, ast, tokens); - buildHighlights(documentPath, visibleImportedTopDecls); - } - - public void registerDocument( - final Path documentPath, - final PbsAst.File ast, - final List tokens) { - final Path normalizedDocumentPath = normalize(documentPath); - tokensByDocument.put(normalizedDocumentPath, List.copyOf(tokens)); - final List documentSymbols = new ArrayList<>(); - for (final PbsAst.TopDecl topDecl : ast.topDecls()) { - final LspSymbolDTO symbol = symbolForTopDecl(normalizedDocumentPath, topDecl); - if (symbol == null) { - continue; - } - documentSymbols.add(symbol); - workspaceSymbols.add(symbol); - symbolsByName.computeIfAbsent(symbol.name(), ignored -> new ArrayList<>()).add(symbol); - for (final LspSymbolDTO child : symbol.children()) { - symbolsByName.computeIfAbsent(child.name(), ignored -> new ArrayList<>()).add(child); - } - } - documentSymbolsByDocument.put(normalizedDocumentPath, List.copyOf(documentSymbols)); - structuralAnchorsByDocument.put( - normalizedDocumentPath, - structuralAnchors(documentSymbols, tokens)); - } - - public void buildHighlights( - final Path documentPath, - final List visibleImportedTopDecls) { - final Path normalizedDocumentPath = normalize(documentPath); - final List tokens = tokensByDocument.getOrDefault(normalizedDocumentPath, List.of()); - final Map visibleKindsByName = new LinkedHashMap<>(); - for (final var entry : symbolsByName.entrySet()) { - if (entry.getValue().isEmpty()) { - continue; - } - visibleKindsByName.putIfAbsent(entry.getKey(), entry.getValue().getFirst().kind()); - } - for (final LspSymbolDTO symbol : documentSymbolsByDocument.getOrDefault(normalizedDocumentPath, List.of())) { - visibleKindsByName.putIfAbsent(symbol.name(), symbol.kind()); - for (final LspSymbolDTO child : symbol.children()) { - visibleKindsByName.putIfAbsent(child.name(), child.kind()); - } - } - for (final PbsAst.TopDecl topDecl : visibleImportedTopDecls) { - final LspSymbolKind visibleKind = symbolKindForTopDecl(topDecl); - final String visibleName = topDeclName(topDecl); - if (visibleKind == null || visibleName == null || visibleName.isBlank()) { - continue; - } - visibleKindsByName.putIfAbsent(visibleName, visibleKind); - } - semanticHighlightsByDocument.put( - normalizedDocumentPath, - buildSemanticHighlights(tokens, visibleKindsByName)); - } - - private List buildSemanticHighlights( - final List tokens, - final Map visibleKindsByName) { - final List highlights = new ArrayList<>(); - for (int index = 0; index < tokens.size(); index++) { - final PbsToken token = tokens.get(index); - if (token.kind() == PbsTokenKind.EOF) { - continue; - } - final String semanticKey = semanticKey(tokens, index, visibleKindsByName); - if (semanticKey == null || semanticKey.isBlank()) { - continue; - } - highlights.add(new LspHighlightSpanDTO( - new LspRangeDTO(token.start(), token.end()), - semanticKey)); - } - return List.copyOf(highlights); - } - - private String semanticKey( - final List tokens, - final int tokenIndex, - final Map visibleKindsByName) { - final PbsToken token = tokens.get(tokenIndex); - if (isLifecycleAttributeToken(tokens, tokenIndex)) { - return PbsSemanticKind.LIFECYCLE.semanticKey(); - } - final PbsSemanticKind semanticKind = token.kind() == p.studio.compiler.pbs.lexer.PbsTokenKind.IDENTIFIER - ? semanticKindForIdentifier(token.lexeme(), visibleKindsByName) - : PbsSemanticKind.forToken(token); - return semanticKind == null ? null : semanticKind.semanticKey(); - } - - private boolean isLifecycleAttributeToken(final List tokens, final int tokenIndex) { - if (tokenIndex < 0 || tokenIndex >= tokens.size()) { - return false; - } - final PbsToken token = tokens.get(tokenIndex); - return switch (token.kind()) { - case LEFT_BRACKET -> hasLifecycleAttributeWindow(tokens, tokenIndex, tokenIndex + 1, tokenIndex + 2); - case IDENTIFIER -> hasLifecycleAttributeWindow(tokens, tokenIndex - 1, tokenIndex, tokenIndex + 1); - case RIGHT_BRACKET -> hasLifecycleAttributeWindow(tokens, tokenIndex - 2, tokenIndex - 1, tokenIndex); - default -> false; - }; - } - - private boolean hasLifecycleAttributeWindow( - final List tokens, - final int leftBracketIndex, - final int identifierIndex, - final int rightBracketIndex) { - if (leftBracketIndex < 0 || rightBracketIndex >= tokens.size()) { - return false; - } - return tokens.get(leftBracketIndex).kind() == PbsTokenKind.LEFT_BRACKET - && tokens.get(identifierIndex).kind() == PbsTokenKind.IDENTIFIER - && isLifecycleAttributeName(tokens.get(identifierIndex).lexeme()) - && tokens.get(rightBracketIndex).kind() == PbsTokenKind.RIGHT_BRACKET; - } - - private boolean isLifecycleAttributeName(final String lexeme) { - return "Init".equals(lexeme) || "Frame".equals(lexeme); - } - - private PbsSemanticKind semanticKindForIdentifier( - final String lexeme, - final Map visibleKindsByName) { - final LspSymbolKind kind = visibleKindsByName.get(lexeme); - if (kind == null) { - return PbsSemanticKind.IDENTIFIER; - } - return switch (kind) { - case FUNCTION -> PbsSemanticKind.FUNCTION; - case METHOD -> PbsSemanticKind.METHOD; - case CONSTRUCTOR -> PbsSemanticKind.CONSTRUCTOR; - case STRUCT -> PbsSemanticKind.STRUCT; - case CONTRACT -> PbsSemanticKind.CONTRACT; - case HOST -> PbsSemanticKind.HOST; - case BUILTIN_TYPE -> PbsSemanticKind.BUILTIN_TYPE; - case SERVICE -> PbsSemanticKind.SERVICE; - case ERROR -> PbsSemanticKind.ERROR; - case ENUM -> PbsSemanticKind.ENUM; - case CALLBACK -> PbsSemanticKind.CALLBACK; - case GLOBAL -> PbsSemanticKind.GLOBAL; - case CONST -> PbsSemanticKind.CONST; - case IMPLEMENTS -> PbsSemanticKind.IMPLEMENTS; - default -> PbsSemanticKind.IDENTIFIER; - }; - } - - private String topDeclName(final PbsAst.TopDecl topDecl) { - if (topDecl instanceof PbsAst.FunctionDecl functionDecl) { - return functionDecl.name(); - } - if (topDecl instanceof PbsAst.StructDecl structDecl) { - return structDecl.name(); - } - if (topDecl instanceof PbsAst.ContractDecl contractDecl) { - return contractDecl.name(); - } - if (topDecl instanceof PbsAst.HostDecl hostDecl) { - return hostDecl.name(); - } - if (topDecl instanceof PbsAst.BuiltinTypeDecl builtinTypeDecl) { - return builtinTypeDecl.name(); - } - if (topDecl instanceof PbsAst.ServiceDecl serviceDecl) { - return serviceDecl.name(); - } - if (topDecl instanceof PbsAst.ErrorDecl errorDecl) { - return errorDecl.name(); - } - if (topDecl instanceof PbsAst.EnumDecl enumDecl) { - return enumDecl.name(); - } - if (topDecl instanceof PbsAst.CallbackDecl callbackDecl) { - return callbackDecl.name(); - } - if (topDecl instanceof PbsAst.GlobalDecl globalDecl) { - return globalDecl.name(); - } - if (topDecl instanceof PbsAst.ConstDecl constDecl) { - return constDecl.name(); - } - if (topDecl instanceof PbsAst.ImplementsDecl implementsDecl) { - return implementsDecl.binderName(); - } - return null; - } - - private LspSymbolKind symbolKindForTopDecl(final PbsAst.TopDecl topDecl) { - if (topDecl instanceof PbsAst.FunctionDecl) { - return LspSymbolKind.FUNCTION; - } - if (topDecl instanceof PbsAst.StructDecl) { - return LspSymbolKind.STRUCT; - } - if (topDecl instanceof PbsAst.ContractDecl) { - return LspSymbolKind.CONTRACT; - } - if (topDecl instanceof PbsAst.HostDecl) { - return LspSymbolKind.HOST; - } - if (topDecl instanceof PbsAst.BuiltinTypeDecl) { - return LspSymbolKind.BUILTIN_TYPE; - } - if (topDecl instanceof PbsAst.ServiceDecl) { - return LspSymbolKind.SERVICE; - } - if (topDecl instanceof PbsAst.ErrorDecl) { - return LspSymbolKind.ERROR; - } - if (topDecl instanceof PbsAst.EnumDecl) { - return LspSymbolKind.ENUM; - } - if (topDecl instanceof PbsAst.CallbackDecl) { - return LspSymbolKind.CALLBACK; - } - if (topDecl instanceof PbsAst.GlobalDecl) { - return LspSymbolKind.GLOBAL; - } - if (topDecl instanceof PbsAst.ConstDecl) { - return LspSymbolKind.CONST; - } - if (topDecl instanceof PbsAst.ImplementsDecl) { - return LspSymbolKind.IMPLEMENTS; - } - return null; - } - - private LspSymbolDTO symbolForTopDecl( - final Path documentPath, - final PbsAst.TopDecl topDecl) { - if (topDecl instanceof PbsAst.FunctionDecl functionDecl) { - return symbol( - documentPath, - functionDecl.name(), - LspSymbolKind.FUNCTION, - functionDecl.span(), - localSymbolsInBlock(documentPath, functionDecl.body())); - } - if (topDecl instanceof PbsAst.StructDecl structDecl) { - return symbol(documentPath, structDecl.name(), LspSymbolKind.STRUCT, structDecl.span(), structChildren(documentPath, structDecl)); - } - if (topDecl instanceof PbsAst.ContractDecl( - String name, p.studio.utilities.structures.ReadOnlyList signatures, Span span - )) { - return symbol(documentPath, name, LspSymbolKind.CONTRACT, span, signatureChildren(documentPath, signatures.asList())); - } - if (topDecl instanceof PbsAst.HostDecl( - String name, p.studio.utilities.structures.ReadOnlyList signatures, Span span - )) { - return symbol(documentPath, name, LspSymbolKind.HOST, span, signatureChildren(documentPath, signatures.asList())); - } - if (topDecl instanceof PbsAst.BuiltinTypeDecl builtinTypeDecl) { - return symbol(documentPath, builtinTypeDecl.name(), LspSymbolKind.BUILTIN_TYPE, builtinTypeDecl.span(), signatureChildren(documentPath, builtinTypeDecl.signatures().asList())); - } - if (topDecl instanceof PbsAst.ServiceDecl( - String name, p.studio.utilities.structures.ReadOnlyList methods, Span span - )) { - return symbol(documentPath, name, LspSymbolKind.SERVICE, span, functionChildren(documentPath, methods.asList())); - } - if (topDecl instanceof PbsAst.ErrorDecl errorDecl) { - return symbol(documentPath, errorDecl.name(), LspSymbolKind.ERROR, errorDecl.span(), List.of()); - } - if (topDecl instanceof PbsAst.EnumDecl enumDecl) { - return symbol(documentPath, enumDecl.name(), LspSymbolKind.ENUM, enumDecl.span(), List.of()); - } - if (topDecl instanceof PbsAst.CallbackDecl callbackDecl) { - return symbol(documentPath, callbackDecl.name(), LspSymbolKind.CALLBACK, callbackDecl.span(), List.of()); - } - if (topDecl instanceof PbsAst.GlobalDecl globalDecl) { - return symbol(documentPath, globalDecl.name(), LspSymbolKind.GLOBAL, globalDecl.span(), List.of()); - } - if (topDecl instanceof PbsAst.ConstDecl constDecl) { - return symbol(documentPath, constDecl.name(), LspSymbolKind.CONST, constDecl.span(), List.of()); - } - if (topDecl instanceof PbsAst.ImplementsDecl implementsDecl) { - return symbol(documentPath, implementsDecl.binderName(), LspSymbolKind.IMPLEMENTS, implementsDecl.span(), functionChildren(documentPath, implementsDecl.methods().asList())); - } - return null; - } - - private List structChildren( - final Path documentPath, - final PbsAst.StructDecl structDecl) { - final List children = new ArrayList<>(functionChildren(documentPath, structDecl.methods().asList())); - for (final PbsAst.CtorDecl ctorDecl : structDecl.ctors()) { - children.add(symbol( - documentPath, - ctorDecl.name(), - LspSymbolKind.CONSTRUCTOR, - ctorDecl.span(), - localSymbolsInBlock(documentPath, ctorDecl.body()))); - } - return List.copyOf(children); - } - - private List functionChildren( - final Path documentPath, - final List functions) { - final List children = new ArrayList<>(); - for (final PbsAst.FunctionDecl functionDecl : functions) { - children.add(symbol( - documentPath, - functionDecl.name(), - LspSymbolKind.METHOD, - functionDecl.span(), - localSymbolsInBlock(documentPath, functionDecl.body()))); - } - return List.copyOf(children); - } - - private List localSymbolsInBlock( - final Path documentPath, - final PbsAst.Block block) { - final List children = new ArrayList<>(); - for (final PbsAst.Statement statement : block.statements().asList()) { - children.addAll(localSymbolsInStatement(documentPath, statement)); - } - if (block.tailExpression() != null) { - children.addAll(localSymbolsInExpression(documentPath, block.tailExpression())); - } - return List.copyOf(children); - } - - private List localSymbolsInStatement( - final Path documentPath, - final PbsAst.Statement statement) { - return switch (statement) { - case PbsAst.LetStatement letStatement -> localSymbolsInExpression(documentPath, letStatement.initializer()); - case PbsAst.AssignStatement assignStatement -> localSymbolsInExpression(documentPath, assignStatement.value()); - case PbsAst.ReturnStatement returnStatement -> localSymbolsInNullableExpression(documentPath, returnStatement.value()); - case PbsAst.IfStatement ifStatement -> List.of(symbol( - documentPath, - "if", - LspSymbolKind.IF, - ifStatement.span(), - children( - localSymbolsInBlock(documentPath, ifStatement.thenBlock()), - ifStatement.elseIf() == null ? List.of() : localSymbolsInStatement(documentPath, ifStatement.elseIf()), - ifStatement.elseBlock() == null ? List.of() : localSymbolsInBlock(documentPath, ifStatement.elseBlock())))); - case PbsAst.ForStatement forStatement -> List.of(symbol( - documentPath, - "for " + forStatement.iteratorName(), - LspSymbolKind.FOR, - forStatement.span(), - localSymbolsInBlock(documentPath, forStatement.body()))); - case PbsAst.WhileStatement whileStatement -> List.of(symbol( - documentPath, - "while", - LspSymbolKind.WHILE, - whileStatement.span(), - localSymbolsInBlock(documentPath, whileStatement.body()))); - case PbsAst.ExpressionStatement expressionStatement -> localSymbolsInExpression(documentPath, expressionStatement.expression()); - case PbsAst.BreakStatement ignored -> List.of(); - case PbsAst.ContinueStatement ignored -> List.of(); - }; - } - - private List localSymbolsInExpression( - final Path documentPath, - final PbsAst.Expression expression) { - return switch (expression) { - case PbsAst.IfExpr ifExpr -> List.of(symbol( - documentPath, - "if", - LspSymbolKind.IF, - ifExpr.span(), - children( - localSymbolsInBlock(documentPath, ifExpr.thenBlock()), - localSymbolsInExpression(documentPath, ifExpr.elseExpression())))); - case PbsAst.SwitchExpr switchExpr -> List.of(symbol( - documentPath, - "switch", - LspSymbolKind.SWITCH, - switchExpr.span(), - childrenFromSwitchArms(documentPath, switchExpr.arms().asList()))); - case PbsAst.HandleExpr handleExpr -> List.of(symbol( - documentPath, - "handle", - LspSymbolKind.HANDLE, - handleExpr.span(), - childrenFromHandleArms(documentPath, handleExpr.arms().asList()))); - case PbsAst.BlockExpr blockExpr -> localSymbolsInBlock(documentPath, blockExpr.block()); - case PbsAst.ElseExpr elseExpr -> children( - localSymbolsInExpression(documentPath, elseExpr.optionalExpression()), - localSymbolsInExpression(documentPath, elseExpr.fallbackExpression())); - case PbsAst.UnaryExpr unaryExpr -> localSymbolsInExpression(documentPath, unaryExpr.expression()); - case PbsAst.BinaryExpr binaryExpr -> children( - localSymbolsInExpression(documentPath, binaryExpr.left()), - localSymbolsInExpression(documentPath, binaryExpr.right())); - case PbsAst.ApplyExpr applyExpr -> children( - localSymbolsInExpression(documentPath, applyExpr.callee()), - localSymbolsInExpression(documentPath, applyExpr.argument())); - case PbsAst.AsExpr asExpr -> localSymbolsInExpression(documentPath, asExpr.expression()); - case PbsAst.CallExpr callExpr -> { - final List> nested = new ArrayList<>(); - nested.add(localSymbolsInExpression(documentPath, callExpr.callee())); - for (final PbsAst.Expression argument : callExpr.arguments().asList()) { - nested.add(localSymbolsInExpression(documentPath, argument)); - } - yield children(nested.toArray(List[]::new)); - } - case PbsAst.MemberExpr memberExpr -> localSymbolsInExpression(documentPath, memberExpr.receiver()); - case PbsAst.PropagateExpr propagateExpr -> localSymbolsInExpression(documentPath, propagateExpr.expression()); - case PbsAst.GroupExpr groupExpr -> localSymbolsInExpression(documentPath, groupExpr.expression()); - case PbsAst.NewExpr newExpr -> { - final List> nested = new ArrayList<>(); - for (final PbsAst.Expression argument : newExpr.arguments().asList()) { - nested.add(localSymbolsInExpression(documentPath, argument)); - } - yield children(nested.toArray(List[]::new)); - } - case PbsAst.BindExpr bindExpr -> localSymbolsInExpression(documentPath, bindExpr.contextExpression()); - case PbsAst.SomeExpr someExpr -> localSymbolsInExpression(documentPath, someExpr.value()); - case PbsAst.OkExpr okExpr -> localSymbolsInExpression(documentPath, okExpr.value()); - case PbsAst.TupleExpr tupleExpr -> { - final List> nested = new ArrayList<>(); - for (final PbsAst.TupleItem item : tupleExpr.items().asList()) { - nested.add(localSymbolsInExpression(documentPath, item.expression())); - } - yield children(nested.toArray(List[]::new)); - } - case PbsAst.IdentifierExpr ignored -> List.of(); - case PbsAst.IntLiteralExpr ignored -> List.of(); - case PbsAst.FloatLiteralExpr ignored -> List.of(); - case PbsAst.BoundedLiteralExpr ignored -> List.of(); - case PbsAst.StringLiteralExpr ignored -> List.of(); - case PbsAst.BoolLiteralExpr ignored -> List.of(); - case PbsAst.ThisExpr ignored -> List.of(); - case PbsAst.NoneExpr ignored -> List.of(); - case PbsAst.ErrExpr ignored -> List.of(); - case PbsAst.UnitExpr ignored -> List.of(); - }; - } - - private List childrenFromSwitchArms( - final Path documentPath, - final List arms) { - final List children = new ArrayList<>(); - for (final PbsAst.SwitchArm arm : arms) { - children.addAll(localSymbolsInBlock(documentPath, arm.block())); - } - return List.copyOf(children); - } - - private List childrenFromHandleArms( - final Path documentPath, - final List arms) { - final List children = new ArrayList<>(); - for (final PbsAst.HandleArm arm : arms) { - children.addAll(localSymbolsInBlock(documentPath, arm.block())); - } - return List.copyOf(children); - } - - private List localSymbolsInNullableExpression( - final Path documentPath, - final PbsAst.Expression expression) { - return expression == null ? List.of() : localSymbolsInExpression(documentPath, expression); - } - - @SafeVarargs - private static List children(final List... parts) { - final List children = new ArrayList<>(); - for (final List part : parts) { - if (part == null || part.isEmpty()) { - continue; - } - children.addAll(part); - } - return List.copyOf(children); - } - - private List signatureChildren( - final Path documentPath, - final List signatures) { - final List children = new ArrayList<>(); - for (final PbsAst.FunctionSignature signature : signatures) { - children.add(symbol(documentPath, signature.name(), LspSymbolKind.METHOD, signature.span(), List.of())); - } - return List.copyOf(children); - } - - private LspSymbolDTO symbol( - final Path documentPath, - final String name, - final LspSymbolKind kind, - final Span span, - final List children) { - return new LspSymbolDTO( - Objects.requireNonNullElse(name, kind.name().toLowerCase()), - kind, - documentPath, - new LspRangeDTO((int) span.getStart(), (int) span.getEnd()), - children); - } - - private List structuralAnchors( - final List documentSymbols, - final List tokens) { - final List anchors = new ArrayList<>(); - for (final LspSymbolDTO symbol : documentSymbols) { - final LspStructuralAnchorDTO anchor = structuralAnchor(symbol, tokens); - if (anchor != null) { - anchors.add(anchor); - } - } - return List.copyOf(anchors); - } - - private LspStructuralAnchorDTO structuralAnchor( - final LspSymbolDTO symbol, - final List tokens) { - final List children = new ArrayList<>(); - for (final LspSymbolDTO child : symbol.children()) { - final LspStructuralAnchorDTO anchorChild = structuralAnchor(child, tokens); - if (anchorChild != null) { - children.add(anchorChild); - } - } - final AnchorPair anchorPair = anchorPair(symbol.range(), tokens); - if (anchorPair == null) { - if (children.isEmpty()) { - return null; - } - return new LspStructuralAnchorDTO(symbol.range(), symbol.range(), symbol.range(), children); - } - return new LspStructuralAnchorDTO(symbol.range(), anchorPair.start(), anchorPair.end(), children); - } - - private AnchorPair anchorPair( - final LspRangeDTO range, - final List tokens) { - PbsToken firstLeftBrace = null; - PbsToken lastRightBrace = null; - for (final PbsToken token : tokens) { - if (token.kind() == PbsTokenKind.EOF) { - continue; - } - if (token.start() < range.startOffset() || token.end() > range.endOffset()) { - continue; - } - if (token.kind() == PbsTokenKind.LEFT_BRACE && firstLeftBrace == null) { - firstLeftBrace = token; - } - if (token.kind() == PbsTokenKind.RIGHT_BRACE) { - lastRightBrace = token; - } - } - if (firstLeftBrace == null || lastRightBrace == null || lastRightBrace.start() < firstLeftBrace.start()) { - return null; - } - return new AnchorPair( - new LspRangeDTO(firstLeftBrace.start(), firstLeftBrace.end()), - new LspRangeDTO(lastRightBrace.start(), lastRightBrace.end())); - } - - public Map> semanticHighlightsByDocument() { - return Map.copyOf(semanticHighlightsByDocument); - } - - public Map> documentSymbolsByDocument() { - return Map.copyOf(documentSymbolsByDocument); - } - - public Map> structuralAnchorsByDocument() { - return Map.copyOf(structuralAnchorsByDocument); - } - - public List workspaceSymbols() { - return List.copyOf(workspaceSymbols); - } - - public Map> symbolsByName() { - final Map> frozen = new LinkedHashMap<>(); - for (final var entry : symbolsByName.entrySet()) { - frozen.put(entry.getKey(), List.copyOf(entry.getValue())); - } - return Map.copyOf(frozen); - } - - public Map> tokensByDocument() { - return Map.copyOf(tokensByDocument); - } - - private record AnchorPair( - LspRangeDTO start, - LspRangeDTO end) { - } -} diff --git a/prometeu-lsp/prometeu-lsp-v1/src/test/java/p/studio/lsp/LspServiceImplTest.java b/prometeu-lsp/prometeu-lsp-v1/src/test/java/p/studio/lsp/LspServiceImplTest.java deleted file mode 100644 index 69836c6b..00000000 --- a/prometeu-lsp/prometeu-lsp-v1/src/test/java/p/studio/lsp/LspServiceImplTest.java +++ /dev/null @@ -1,427 +0,0 @@ -package p.studio.lsp; - -import org.junit.jupiter.api.Test; -import org.junit.jupiter.api.io.TempDir; -import p.studio.lsp.dtos.LspStructuralAnchorDTO; -import p.studio.lsp.messages.LspProjectContext; -import p.studio.lsp.dtos.LspDefinitionTargetDTO; -import p.studio.lsp.messages.LspAnalyzeDocumentRequest; -import p.studio.lsp.messages.LspDefinitionRequest; -import p.studio.vfs.*; -import p.studio.vfs.messages.*; - -import java.nio.file.Files; -import java.nio.file.Path; -import java.util.List; -import java.util.Map; - -import static org.junit.jupiter.api.Assertions.assertEquals; -import static org.junit.jupiter.api.Assertions.assertFalse; -import static org.junit.jupiter.api.Assertions.assertTrue; - -final class LspServiceImplTest { - @TempDir - Path tempDir; - - private static final String OVERLAY_SOURCE = """ - fn helper_call() -> void - { - if true { - helper(); - } - while false { - helper(); - } - let value = switch true { - true: { 1 }, - default: { 2 } - }; - let recovered = handle helper_result() { - _: { - ok(0) - } - }; - } - """; - - private static final String SERVICE_SOURCE = """ - declare service Game { - fn tick(x: int) -> int { return x; } - } - - fn main() -> void { - Game.tick(1); - } - """; - - private static final String SDK_IMPORT_SOURCE = """ - import { Composer } from @sdk:composer; - - fn main() -> void { - Composer.emit_sprite(1, 0, 0, 0, 0, 0, false, false, 0); - } - """; - - private static final String PROJECT_IMPORT_SOURCE = """ - import { Color } from @app:graphics; - - fn main(color: Color) -> Color { - return color; - } - """; - - @Test - void analyzeDocumentUsesVfsOverlayForRequestedDocumentAndFilesystemFallbackForClosedFiles() throws Exception { - final Path projectRoot = createProject(); - final Path mainFile = projectRoot.resolve("src/main.pbs"); - final Path helperFile = projectRoot.resolve("src/helper.pbs"); - Files.writeString(mainFile, "fn broken( -> void {}\n"); - Files.writeString(helperFile, "fn helper() -> void {}\n"); - - final VfsProjectDocument delegate = new FilesystemProjectDocumentVfsFactory().open(projectContext(projectRoot)); - final LspService service = new LspServiceImpl( - new LspProjectContext("Example", "pbs", projectRoot), - new OverlayVfsProjectDocument(delegate, mainFile, OVERLAY_SOURCE)); - - final var analysis = service.analyzeDocument(new LspAnalyzeDocumentRequest(mainFile)); - - assertEquals("pbs-function", semanticKeyForLexeme(analysis, OVERLAY_SOURCE, "helper_call")); - assertEquals("pbs-function", semanticKeyForLexeme(analysis, OVERLAY_SOURCE, "helper")); - assertEquals(List.of("/themes/pbs/semantic-highlighting.css"), analysis.semanticPresentation().resources()); - assertTrue(analysis.semanticPresentation().semanticKeys().contains("pbs-function")); - assertFalse(analysis.inlineHints().isEmpty(), analysis.toString()); - - assertTrue( - analysis.documentSymbols().stream().anyMatch(symbol -> symbol.name().equals("helper_call")), - analysis.toString()); - assertTrue( - flatten(analysis.documentSymbols()).stream().anyMatch(symbol -> symbol.kind() == p.studio.lsp.messages.LspSymbolKind.IF), - analysis.toString()); - assertTrue( - flatten(analysis.documentSymbols()).stream().anyMatch(symbol -> symbol.kind() == p.studio.lsp.messages.LspSymbolKind.WHILE), - analysis.toString()); - assertTrue( - flatten(analysis.documentSymbols()).stream().anyMatch(symbol -> symbol.kind() == p.studio.lsp.messages.LspSymbolKind.SWITCH), - analysis.toString()); - assertTrue( - flatten(analysis.documentSymbols()).stream().anyMatch(symbol -> symbol.kind() == p.studio.lsp.messages.LspSymbolKind.HANDLE), - analysis.toString()); - assertFalse(analysis.structuralAnchors().isEmpty(), analysis.toString()); - assertEquals(OVERLAY_SOURCE.indexOf("{"), analysis.structuralAnchors().getFirst().startAnchor().startOffset()); - assertTrue( - flattenAnchors(analysis.structuralAnchors()).stream().anyMatch(anchor -> - anchor.startAnchor().startOffset() == OVERLAY_SOURCE.indexOf("if true {") + "if true ".length()), - analysis.toString()); - assertTrue( - analysis.workspaceSymbols().stream().anyMatch(symbol -> - symbol.name().equals("helper") && symbol.documentPath().equals(normalize(helperFile))), - analysis.toString()); - - final int offset = OVERLAY_SOURCE.indexOf("helper();"); - final var definition = service.definition(new LspDefinitionRequest(mainFile, offset)); - final List targets = definition.targets(); - - assertEquals(2, targets.size()); - assertEquals(normalize(helperFile), targets.getFirst().documentPath()); - assertEquals("helper", targets.getFirst().name()); - } - - @Test - void analyzeDocumentSurfacesDiagnosticsWithoutAbortingSemanticRead() throws Exception { - final Path projectRoot = createProject(); - final Path mainFile = projectRoot.resolve("src/main.pbs"); - Files.writeString(mainFile, """ - fn main( -> void - { - helper(); - } - """); - - final VfsProjectDocument vfs = new FilesystemProjectDocumentVfsFactory().open(projectContext(projectRoot)); - final LspService service = new LspServiceImpl( - new LspProjectContext("Example", "pbs", projectRoot), - vfs); - - final var analysis = service.analyzeDocument(new LspAnalyzeDocumentRequest(mainFile)); - - assertFalse(analysis.diagnostics().isEmpty(), analysis.toString()); - assertTrue(analysis.diagnostics().stream().allMatch(diagnostic -> - diagnostic.documentPath().equals(normalize(mainFile)))); - } - - @Test - void analyzeDocumentHighlightsServiceIdentifiersWithServiceSemanticKey() throws Exception { - final Path projectRoot = createProject(); - final Path mainFile = projectRoot.resolve("src/main.pbs"); - Files.writeString(mainFile, SERVICE_SOURCE); - - final VfsProjectDocument vfs = new FilesystemProjectDocumentVfsFactory().open(projectContext(projectRoot)); - final LspService service = new LspServiceImpl( - new LspProjectContext("Example", "pbs", projectRoot), - vfs); - - final var analysis = service.analyzeDocument(new LspAnalyzeDocumentRequest(mainFile)); - - assertEquals("pbs-service", semanticKeyForLexeme(analysis, SERVICE_SOURCE, "Game")); - assertTrue(flatten(analysis.documentSymbols()).stream().anyMatch(symbol -> - symbol.kind() == p.studio.lsp.messages.LspSymbolKind.SERVICE && symbol.name().equals("Game"))); - } - - @Test - void analyzeDocumentHighlightsSdkImportedHostIdentifiersWithHostSemanticKey() throws Exception { - final Path projectRoot = createProject(); - final Path mainFile = projectRoot.resolve("src/main.pbs"); - Files.writeString(mainFile, SDK_IMPORT_SOURCE); - - final VfsProjectDocument vfs = new FilesystemProjectDocumentVfsFactory().open(projectContext(projectRoot)); - final LspService service = new LspServiceImpl( - new LspProjectContext("Example", "pbs", projectRoot), - vfs); - - final var analysis = service.analyzeDocument(new LspAnalyzeDocumentRequest(mainFile)); - - assertEquals(List.of("pbs-service", "pbs-service"), semanticKeysForLexeme(analysis, SDK_IMPORT_SOURCE, "Composer")); - } - - @Test - void analyzeDocumentHighlightsProjectImportedStructIdentifiersWithStructSemanticKey() throws Exception { - final Path projectRoot = createProject(); - final Path mainFile = projectRoot.resolve("src/main.pbs"); - final Path graphicsDir = projectRoot.resolve("src/graphics"); - final Path graphicsFile = graphicsDir.resolve("types.pbs"); - final Path graphicsBarrel = graphicsDir.resolve("mod.barrel"); - Files.createDirectories(graphicsDir); - Files.writeString(mainFile, PROJECT_IMPORT_SOURCE); - Files.writeString(graphicsFile, "declare struct Color(raw: int);\n"); - Files.writeString(graphicsBarrel, "pub struct Color;\n"); - - final VfsProjectDocument vfs = new FilesystemProjectDocumentVfsFactory().open(projectContext(projectRoot)); - final LspService service = new LspServiceImpl( - new LspProjectContext("Example", "pbs", projectRoot), - vfs); - - final var analysis = service.analyzeDocument(new LspAnalyzeDocumentRequest(mainFile)); - - assertEquals(List.of("pbs-struct", "pbs-struct", "pbs-struct"), semanticKeysForLexeme(analysis, PROJECT_IMPORT_SOURCE, "Color")); - } - - @Test - void analyzeDocumentReturnsDedicatedInlineHintTransportSurface() throws Exception { - final Path projectRoot = createProject(); - final Path mainFile = projectRoot.resolve("src/main.pbs"); - final String source = "fn main() -> void { let value = 1; }\n"; - Files.writeString(mainFile, source); - - final VfsProjectDocument vfs = new FilesystemProjectDocumentVfsFactory().open(projectContext(projectRoot)); - final LspService service = new LspServiceImpl( - new LspProjectContext("Example", "pbs", projectRoot), - vfs); - - final var analysis = service.analyzeDocument(new LspAnalyzeDocumentRequest(mainFile)); - - assertEquals(1, analysis.inlineHints().size(), analysis.toString()); - assertEquals("int", analysis.inlineHints().getFirst().label()); - assertEquals("type", analysis.inlineHints().getFirst().category()); - assertEquals("value", sourceSlice(source, analysis.inlineHints().getFirst().anchor())); - } - - @Test - void analyzeDocumentPreservesValidInlineHintsUnderPartialDegradation() throws Exception { - final Path projectRoot = createProject(); - final Path mainFile = projectRoot.resolve("src/main.pbs"); - final String source = """ - fn ok() -> void { - let value = 1; - return; - } - - fn broken( -> void { - let missing = 2; - } - """; - Files.writeString(mainFile, source); - - final VfsProjectDocument vfs = new FilesystemProjectDocumentVfsFactory().open(projectContext(projectRoot)); - final LspService service = new LspServiceImpl( - new LspProjectContext("Example", "pbs", projectRoot), - vfs); - - final var analysis = service.analyzeDocument(new LspAnalyzeDocumentRequest(mainFile)); - - assertFalse(analysis.diagnostics().isEmpty(), analysis.toString()); - assertEquals(1, analysis.inlineHints().size(), analysis.toString()); - assertEquals("int", analysis.inlineHints().getFirst().label()); - assertEquals("value", sourceSlice(source, analysis.inlineHints().getFirst().anchor())); - } - - private Path createProject() throws Exception { - final Path src = Files.createDirectories(tempDir.resolve("src")); - Files.writeString(tempDir.resolve("prometeu.json"), """ - { - "name": "Example", - "version": "1.0.0", - "language": "pbs", - "stdlib": "1", - "dependencies": [] - } - """); - Files.writeString(src.resolve("mod.barrel"), """ - pub fn helper() -> void; - pub fn helper_result() -> result int; - pub error MyError; - pub service Log; - """); - Files.writeString(src.resolve("helper.pbs"), "fn helper() -> void {}\n"); - Files.writeString(src.resolve("helper_result.pbs"), """ - declare error MyError { - Failed - } - - fn helper_result() -> result int { - return ok(1); - } - """); - Files.writeString(src.resolve("log.pbs"), """ - declare service Log { - fn failure(message: string) -> void; - } - """); - return tempDir; - } - - private static List flatten( - final List symbols) { - final List flattened = new java.util.ArrayList<>(); - for (final var symbol : symbols) { - flattened.add(symbol); - flattened.addAll(flatten(symbol.children())); - } - return flattened; - } - - private static List flattenAnchors( - final List anchors) { - final List flattened = new java.util.ArrayList<>(); - for (final var anchor : anchors) { - flattened.add(anchor); - flattened.addAll(flattenAnchors(anchor.children())); - } - return flattened; - } - - private VfsProjectContext projectContext(final Path projectRoot) { - return new VfsProjectContext("Example", "pbs", projectRoot); - } - - private static Path normalize(final Path path) { - try { - return path.toAbsolutePath().normalize().toRealPath(); - } catch (Exception exception) { - throw new IllegalStateException(exception); - } - } - - private static String semanticKeyForLexeme( - final p.studio.lsp.messages.LspAnalyzeDocumentResult analysis, - final String source, - final String lexeme) { - return semanticKeysForLexeme(analysis, source, lexeme).stream().findFirst().orElseThrow(); - } - - private static List semanticKeysForLexeme( - final p.studio.lsp.messages.LspAnalyzeDocumentResult analysis, - final String source, - final String lexeme) { - return analysis.semanticHighlights().stream() - .filter(highlight -> lexeme.equals(spanContent(source, highlight.range().startOffset(), highlight.range().endOffset()))) - .map(p.studio.lsp.dtos.LspHighlightSpanDTO::semanticKey) - .toList(); - } - - private static String spanContent( - final String source, - final int start, - final int end) { - if (start < 0 || end > source.length() || start >= end) { - return ""; - } - return source.substring(start, end); - } - - private static String sourceSlice( - final String source, - final p.studio.lsp.dtos.LspRangeDTO range) { - return spanContent(source, range.startOffset(), range.endOffset()); - } - - private static final class OverlayVfsProjectDocument implements VfsProjectDocument { - private final VfsProjectDocument delegate; - private final Path overlayPath; - private final String overlayContent; - - private OverlayVfsProjectDocument( - final VfsProjectDocument delegate, - final Path overlayPath, - final String overlayContent) { - this.delegate = delegate; - this.overlayPath = normalize(overlayPath); - this.overlayContent = overlayContent; - } - - @Override - public VfsProjectContext projectContext() { - return delegate.projectContext(); - } - - @Override - public VfsProjectSnapshot snapshot() { - return delegate.snapshot(); - } - - @Override - public VfsProjectSnapshot refresh() { - return delegate.refresh(); - } - - @Override - public VfsProjectSnapshot refresh(final VfsRefreshRequest request) { - return delegate.refresh(request); - } - - @Override - public VfsDocumentOpenResult openDocument(final Path path) { - final Path normalizedPath = normalize(path); - if (!overlayPath.equals(normalizedPath)) { - return delegate.openDocument(normalizedPath); - } - final VfsDocumentAccessContext accessContext = new VfsDocumentAccessContext( - normalizedPath, - "pbs", - true, - VfsDocumentAccessMode.READ_ONLY, - Map.of()); - return new VfsDocumentOpenResult.VfsTextDocument( - normalizedPath, - normalizedPath.getFileName().toString(), - "pbs", - overlayContent, - "LF", - false, - accessContext); - } - - @Override - public void close() { - delegate.close(); - } - - private static Path normalize(final Path path) { - final Path normalized = path.toAbsolutePath().normalize(); - try { - return Files.exists(normalized) ? normalized.toRealPath() : normalized; - } catch (Exception ignored) { - return normalized; - } - } - } -} diff --git a/prometeu-studio/build.gradle.kts b/prometeu-studio/build.gradle.kts index 5dadc75d..57bf98cc 100644 --- a/prometeu-studio/build.gradle.kts +++ b/prometeu-studio/build.gradle.kts @@ -5,8 +5,6 @@ plugins { dependencies { implementation(project(":prometeu-infra")) - implementation(project(":prometeu-lsp:prometeu-lsp-api")) - implementation(project(":prometeu-vfs:prometeu-vfs-api")) implementation(project(":prometeu-packer:prometeu-packer-api")) implementation(project(":prometeu-compiler:prometeu-compiler-core")) implementation(project(":prometeu-compiler:prometeu-build-pipeline")) diff --git a/prometeu-studio/src/main/java/p/studio/projects/ProjectReference.java b/prometeu-studio/src/main/java/p/studio/projects/ProjectReference.java index c0dbc8ce..20e7fb84 100644 --- a/prometeu-studio/src/main/java/p/studio/projects/ProjectReference.java +++ b/prometeu-studio/src/main/java/p/studio/projects/ProjectReference.java @@ -2,7 +2,6 @@ package p.studio.projects; import org.apache.commons.lang3.StringUtils; import p.packer.messages.PackerProjectContext; -import p.studio.vfs.messages.VfsProjectContext; import java.nio.file.Path; @@ -36,8 +35,4 @@ public record ProjectReference( public PackerProjectContext toPackerProjectContext() { return new PackerProjectContext(name, absoluteRootPath()); } - - public VfsProjectContext toVfsProjectContext() { - return new VfsProjectContext(name, languageId, absoluteRootPath()); - } } diff --git a/prometeu-vfs/prometeu-vfs-api/build.gradle.kts b/prometeu-vfs/prometeu-vfs-api/build.gradle.kts deleted file mode 100644 index a6775d6e..00000000 --- a/prometeu-vfs/prometeu-vfs-api/build.gradle.kts +++ /dev/null @@ -1,3 +0,0 @@ -plugins { - id("gradle.java-library-conventions") -} diff --git a/prometeu-vfs/prometeu-vfs-api/src/main/java/p/studio/vfs/ProjectDocumentVfsFactory.java b/prometeu-vfs/prometeu-vfs-api/src/main/java/p/studio/vfs/ProjectDocumentVfsFactory.java deleted file mode 100644 index fe309951..00000000 --- a/prometeu-vfs/prometeu-vfs-api/src/main/java/p/studio/vfs/ProjectDocumentVfsFactory.java +++ /dev/null @@ -1,7 +0,0 @@ -package p.studio.vfs; - -import p.studio.vfs.messages.VfsProjectContext; - -public interface ProjectDocumentVfsFactory { - VfsProjectDocument open(VfsProjectContext projectContext); -} diff --git a/prometeu-vfs/prometeu-vfs-api/src/main/java/p/studio/vfs/VfsDocumentOpenResult.java b/prometeu-vfs/prometeu-vfs-api/src/main/java/p/studio/vfs/VfsDocumentOpenResult.java deleted file mode 100644 index 4eee7b40..00000000 --- a/prometeu-vfs/prometeu-vfs-api/src/main/java/p/studio/vfs/VfsDocumentOpenResult.java +++ /dev/null @@ -1,40 +0,0 @@ -package p.studio.vfs; - -import p.studio.vfs.messages.VfsDocumentAccessContext; -import p.studio.vfs.messages.VfsUnsupportedReason; - -import java.nio.file.Path; -import java.util.Objects; - -public sealed interface VfsDocumentOpenResult permits VfsDocumentOpenResult.VfsUnsupportedDocument, VfsDocumentOpenResult.VfsTextDocument { - Path path(); - - record VfsUnsupportedDocument( - Path path, - VfsUnsupportedReason reason) implements VfsDocumentOpenResult { - - public VfsUnsupportedDocument { - path = Objects.requireNonNull(path, "path").toAbsolutePath().normalize(); - Objects.requireNonNull(reason, "reason"); - } - } - - record VfsTextDocument( - Path path, - String documentName, - String typeId, - String content, - String lineSeparator, - boolean dirty, - VfsDocumentAccessContext accessContext) implements VfsDocumentOpenResult { - - public VfsTextDocument { - path = Objects.requireNonNull(path, "path").toAbsolutePath().normalize(); - Objects.requireNonNull(documentName, "documentName"); - Objects.requireNonNull(typeId, "typeId"); - Objects.requireNonNull(content, "content"); - Objects.requireNonNull(lineSeparator, "lineSeparator"); - Objects.requireNonNull(accessContext, "accessContext"); - } - } -} diff --git a/prometeu-vfs/prometeu-vfs-api/src/main/java/p/studio/vfs/VfsProjectDocument.java b/prometeu-vfs/prometeu-vfs-api/src/main/java/p/studio/vfs/VfsProjectDocument.java deleted file mode 100644 index 73c5fdbb..00000000 --- a/prometeu-vfs/prometeu-vfs-api/src/main/java/p/studio/vfs/VfsProjectDocument.java +++ /dev/null @@ -1,47 +0,0 @@ -package p.studio.vfs; - -import p.studio.vfs.messages.*; - -import java.nio.file.Path; -import java.util.List; -import java.util.Map; - -public interface VfsProjectDocument extends AutoCloseable { - VfsProjectContext projectContext(); - - VfsProjectSnapshot snapshot(); - - VfsProjectSnapshot refresh(); - - VfsProjectSnapshot refresh(VfsRefreshRequest request); - - VfsDocumentOpenResult openDocument(Path path); - - default VfsDocumentAccessContext accessContext(final Path path) { - throw new UnsupportedOperationException("Document access context is not supported by this VFS implementation."); - } - - default VfsDocumentAccessContext updateAccessContext(final Path path, final Map attributes) { - throw new UnsupportedOperationException("Document access context updates are not supported by this VFS implementation."); - } - - default VfsDocumentOpenResult.VfsTextDocument updateDocument(final Path path, final String content) { - throw new UnsupportedOperationException("Document mutation is not supported by this VFS implementation."); - } - - default VfsDocumentSaveResult saveDocument(final Path path) { - throw new UnsupportedOperationException("Document save is not supported by this VFS implementation."); - } - - default VfsDocumentOpenResult.VfsTextDocument discardDocument(final Path path) { - throw new UnsupportedOperationException("Document discard is not supported by this VFS implementation."); - } - - default List saveAllDocuments() { - return List.of(); - } - - @Override - default void close() { - } -} diff --git a/prometeu-vfs/prometeu-vfs-api/src/main/java/p/studio/vfs/messages/VfsDocumentAccessContext.java b/prometeu-vfs/prometeu-vfs-api/src/main/java/p/studio/vfs/messages/VfsDocumentAccessContext.java deleted file mode 100644 index 40fb7cdb..00000000 --- a/prometeu-vfs/prometeu-vfs-api/src/main/java/p/studio/vfs/messages/VfsDocumentAccessContext.java +++ /dev/null @@ -1,20 +0,0 @@ -package p.studio.vfs.messages; - -import java.nio.file.Path; -import java.util.Map; -import java.util.Objects; - -public record VfsDocumentAccessContext( - Path path, - String typeId, - boolean frontendDocument, - VfsDocumentAccessMode accessMode, - Map attributes) { - - public VfsDocumentAccessContext { - path = Objects.requireNonNull(path, "path").toAbsolutePath().normalize(); - Objects.requireNonNull(typeId, "typeId"); - Objects.requireNonNull(accessMode, "accessMode"); - attributes = Map.copyOf(Objects.requireNonNull(attributes, "attributes")); - } -} diff --git a/prometeu-vfs/prometeu-vfs-api/src/main/java/p/studio/vfs/messages/VfsDocumentAccessMode.java b/prometeu-vfs/prometeu-vfs-api/src/main/java/p/studio/vfs/messages/VfsDocumentAccessMode.java deleted file mode 100644 index 1ebbc417..00000000 --- a/prometeu-vfs/prometeu-vfs-api/src/main/java/p/studio/vfs/messages/VfsDocumentAccessMode.java +++ /dev/null @@ -1,6 +0,0 @@ -package p.studio.vfs.messages; - -public enum VfsDocumentAccessMode { - READ_ONLY, - EDITABLE -} diff --git a/prometeu-vfs/prometeu-vfs-api/src/main/java/p/studio/vfs/messages/VfsDocumentSaveResult.java b/prometeu-vfs/prometeu-vfs-api/src/main/java/p/studio/vfs/messages/VfsDocumentSaveResult.java deleted file mode 100644 index 5ac04114..00000000 --- a/prometeu-vfs/prometeu-vfs-api/src/main/java/p/studio/vfs/messages/VfsDocumentSaveResult.java +++ /dev/null @@ -1,16 +0,0 @@ -package p.studio.vfs.messages; - -import java.nio.file.Path; -import java.util.Objects; - -public record VfsDocumentSaveResult( - Path path, - String typeId, - VfsDocumentSaveStatus status) { - - public VfsDocumentSaveResult { - path = Objects.requireNonNull(path, "path").toAbsolutePath().normalize(); - Objects.requireNonNull(typeId, "typeId"); - Objects.requireNonNull(status, "status"); - } -} diff --git a/prometeu-vfs/prometeu-vfs-api/src/main/java/p/studio/vfs/messages/VfsDocumentSaveStatus.java b/prometeu-vfs/prometeu-vfs-api/src/main/java/p/studio/vfs/messages/VfsDocumentSaveStatus.java deleted file mode 100644 index 2a8ad4d4..00000000 --- a/prometeu-vfs/prometeu-vfs-api/src/main/java/p/studio/vfs/messages/VfsDocumentSaveStatus.java +++ /dev/null @@ -1,7 +0,0 @@ -package p.studio.vfs.messages; - -public enum VfsDocumentSaveStatus { - SAVED, - NO_CHANGES, - READ_ONLY -} diff --git a/prometeu-vfs/prometeu-vfs-api/src/main/java/p/studio/vfs/messages/VfsDocumentTypeIds.java b/prometeu-vfs/prometeu-vfs-api/src/main/java/p/studio/vfs/messages/VfsDocumentTypeIds.java deleted file mode 100644 index f664d59a..00000000 --- a/prometeu-vfs/prometeu-vfs-api/src/main/java/p/studio/vfs/messages/VfsDocumentTypeIds.java +++ /dev/null @@ -1,11 +0,0 @@ -package p.studio.vfs.messages; - -public final class VfsDocumentTypeIds { - public static final String TEXT = "text"; - public static final String JSON = "json"; - public static final String NDJSON = "ndjson"; - public static final String BASH = "bash"; - - private VfsDocumentTypeIds() { - } -} diff --git a/prometeu-vfs/prometeu-vfs-api/src/main/java/p/studio/vfs/messages/VfsProjectContext.java b/prometeu-vfs/prometeu-vfs-api/src/main/java/p/studio/vfs/messages/VfsProjectContext.java deleted file mode 100644 index 81ecd2fb..00000000 --- a/prometeu-vfs/prometeu-vfs-api/src/main/java/p/studio/vfs/messages/VfsProjectContext.java +++ /dev/null @@ -1,16 +0,0 @@ -package p.studio.vfs.messages; - -import java.nio.file.Path; -import java.util.Objects; - -public record VfsProjectContext( - String projectName, - String languageId, - Path rootPath) { - - public VfsProjectContext { - Objects.requireNonNull(projectName, "projectName"); - Objects.requireNonNull(languageId, "languageId"); - rootPath = Objects.requireNonNull(rootPath, "rootPath").toAbsolutePath().normalize(); - } -} diff --git a/prometeu-vfs/prometeu-vfs-api/src/main/java/p/studio/vfs/messages/VfsProjectNode.java b/prometeu-vfs/prometeu-vfs-api/src/main/java/p/studio/vfs/messages/VfsProjectNode.java deleted file mode 100644 index 271bdadc..00000000 --- a/prometeu-vfs/prometeu-vfs-api/src/main/java/p/studio/vfs/messages/VfsProjectNode.java +++ /dev/null @@ -1,19 +0,0 @@ -package p.studio.vfs.messages; - -import java.nio.file.Path; -import java.util.List; -import java.util.Objects; - -public record VfsProjectNode( - Path path, - String displayName, - boolean directory, - boolean taggedSourceRoot, - List children) { - - public VfsProjectNode { - path = Objects.requireNonNull(path, "path").toAbsolutePath().normalize(); - Objects.requireNonNull(displayName, "displayName"); - children = List.copyOf(Objects.requireNonNull(children, "children")); - } -} diff --git a/prometeu-vfs/prometeu-vfs-api/src/main/java/p/studio/vfs/messages/VfsProjectSnapshot.java b/prometeu-vfs/prometeu-vfs-api/src/main/java/p/studio/vfs/messages/VfsProjectSnapshot.java deleted file mode 100644 index 7995d13b..00000000 --- a/prometeu-vfs/prometeu-vfs-api/src/main/java/p/studio/vfs/messages/VfsProjectSnapshot.java +++ /dev/null @@ -1,14 +0,0 @@ -package p.studio.vfs.messages; - -import java.nio.file.Path; -import java.util.Objects; - -public record VfsProjectSnapshot( - Path projectRoot, - VfsProjectNode rootNode) { - - public VfsProjectSnapshot { - projectRoot = Objects.requireNonNull(projectRoot, "projectRoot").toAbsolutePath().normalize(); - Objects.requireNonNull(rootNode, "rootNode"); - } -} diff --git a/prometeu-vfs/prometeu-vfs-api/src/main/java/p/studio/vfs/messages/VfsRefreshRequest.java b/prometeu-vfs/prometeu-vfs-api/src/main/java/p/studio/vfs/messages/VfsRefreshRequest.java deleted file mode 100644 index 955c0cf4..00000000 --- a/prometeu-vfs/prometeu-vfs-api/src/main/java/p/studio/vfs/messages/VfsRefreshRequest.java +++ /dev/null @@ -1,10 +0,0 @@ -package p.studio.vfs.messages; - -import java.nio.file.Path; -import java.util.Objects; - -public record VfsRefreshRequest(Path targetPath) { - public VfsRefreshRequest { - targetPath = Objects.requireNonNull(targetPath, "targetPath").toAbsolutePath().normalize(); - } -} diff --git a/prometeu-vfs/prometeu-vfs-api/src/main/java/p/studio/vfs/messages/VfsUnsupportedReason.java b/prometeu-vfs/prometeu-vfs-api/src/main/java/p/studio/vfs/messages/VfsUnsupportedReason.java deleted file mode 100644 index beeee78a..00000000 --- a/prometeu-vfs/prometeu-vfs-api/src/main/java/p/studio/vfs/messages/VfsUnsupportedReason.java +++ /dev/null @@ -1,10 +0,0 @@ -package p.studio.vfs.messages; - -public enum VfsUnsupportedReason { - OUTSIDE_PROJECT, - NOT_FOUND, - NOT_A_FILE, - NO_HANDLER, - BINARY_CONTENT, - INVALID_UTF8 -} diff --git a/prometeu-vfs/prometeu-vfs-v1/build.gradle.kts b/prometeu-vfs/prometeu-vfs-v1/build.gradle.kts deleted file mode 100644 index 4a0f4a96..00000000 --- a/prometeu-vfs/prometeu-vfs-v1/build.gradle.kts +++ /dev/null @@ -1,9 +0,0 @@ -plugins { - id("gradle.java-library-conventions") -} - -dependencies { - implementation(project(":prometeu-vfs:prometeu-vfs-api")) - implementation(project(":prometeu-compiler:prometeu-compiler-core")) - implementation(project(":prometeu-compiler:prometeu-frontend-registry")) -} diff --git a/prometeu-vfs/prometeu-vfs-v1/src/main/java/p/studio/vfs/FilesystemProjectDocumentVfsFactory.java b/prometeu-vfs/prometeu-vfs-v1/src/main/java/p/studio/vfs/FilesystemProjectDocumentVfsFactory.java deleted file mode 100644 index a60f52ed..00000000 --- a/prometeu-vfs/prometeu-vfs-v1/src/main/java/p/studio/vfs/FilesystemProjectDocumentVfsFactory.java +++ /dev/null @@ -1,12 +0,0 @@ -package p.studio.vfs; - -import p.studio.vfs.messages.VfsProjectContext; - -import java.util.Objects; - -public final class FilesystemProjectDocumentVfsFactory implements ProjectDocumentVfsFactory { - @Override - public VfsProjectDocument open(final VfsProjectContext projectContext) { - return new FilesystemVfsProjectDocument(Objects.requireNonNull(projectContext, "projectContext")); - } -} diff --git a/prometeu-vfs/prometeu-vfs-v1/src/main/java/p/studio/vfs/FilesystemVfsProjectDocument.java b/prometeu-vfs/prometeu-vfs-v1/src/main/java/p/studio/vfs/FilesystemVfsProjectDocument.java deleted file mode 100644 index feac1f57..00000000 --- a/prometeu-vfs/prometeu-vfs-v1/src/main/java/p/studio/vfs/FilesystemVfsProjectDocument.java +++ /dev/null @@ -1,466 +0,0 @@ -package p.studio.vfs; - -import p.studio.compiler.FrontendRegistryService; -import p.studio.compiler.models.FrontendSpec; -import p.studio.vfs.messages.*; - -import java.io.IOException; -import java.io.UncheckedIOException; -import java.nio.ByteBuffer; -import java.nio.charset.CharacterCodingException; -import java.nio.charset.CodingErrorAction; -import java.nio.charset.StandardCharsets; -import java.nio.file.Files; -import java.nio.file.Path; -import java.util.*; -import java.util.stream.Collectors; -import java.util.stream.Stream; - -final class FilesystemVfsProjectDocument implements VfsProjectDocument { - private final VfsProjectContext projectContext; - private final Map editableSnapshots = new LinkedHashMap<>(); - private final Map> accessContextAttributes = new HashMap<>(); - private VfsProjectSnapshot snapshot; - - FilesystemVfsProjectDocument(final VfsProjectContext projectContext) { - this.projectContext = Objects.requireNonNull(projectContext, "projectContext"); - this.snapshot = buildSnapshot(); - } - - @Override - public VfsProjectContext projectContext() { - return projectContext; - } - - @Override - public VfsProjectSnapshot snapshot() { - return snapshot; - } - - @Override - public VfsProjectSnapshot refresh() { - snapshot = buildSnapshot(); - return snapshot; - } - - @Override - public VfsProjectSnapshot refresh(final VfsRefreshRequest request) { - final Path refreshTarget = refreshRootFor(Objects.requireNonNull(request, "request").targetPath()); - if (refreshTarget.equals(projectContext.rootPath())) { - return refresh(); - } - - final Set taggedRoots = taggedSourceRoots(); - final String displayName = refreshTarget.getFileName() == null - ? projectContext.projectName() - : refreshTarget.getFileName().toString(); - final VfsProjectNode refreshedNode = buildNode(refreshTarget, displayName, taggedRoots); - snapshot = new VfsProjectSnapshot( - projectContext.rootPath(), - replaceNode(snapshot.rootNode(), refreshedNode)); - return snapshot; - } - - @Override - public VfsDocumentOpenResult openDocument(final Path path) { - try { - final var supportedDocument = requireSupportedDocument(path); - return openSupportedDocument(supportedDocument); - } catch (UnsupportedDocumentException unsupportedDocumentException) { - return new VfsDocumentOpenResult.VfsUnsupportedDocument( - unsupportedDocumentException.path(), - unsupportedDocumentException.reason()); - } - } - - @Override - public VfsDocumentAccessContext accessContext(final Path path) { - return accessContextFor(requireSupportedDocument(path)); - } - - @Override - public VfsDocumentAccessContext updateAccessContext(final Path path, final Map attributes) { - final var supportedDocument = requireSupportedDocument(path); - accessContextAttributes.put(supportedDocument.path(), Map.copyOf(Objects.requireNonNull(attributes, "attributes"))); - return accessContextFor(supportedDocument); - } - - @Override - public VfsDocumentOpenResult.VfsTextDocument updateDocument(final Path path, final String content) { - final var supportedDocument = requireSupportedDocument(path); - if (supportedDocument.accessMode() != VfsDocumentAccessMode.EDITABLE) { - throw new IllegalStateException("Document is hard read-only: " + supportedDocument.path()); - } - final var normalizedPath = supportedDocument.path(); - final var snapshot = editableSnapshots.computeIfAbsent( - normalizedPath, - ignored -> new EditableDocumentSnapshot( - supportedDocument.content(), - supportedDocument.content(), - supportedDocument.lineSeparator())); - snapshot.content = Objects.requireNonNull(content, "content"); - snapshot.lineSeparator = lineSeparator(snapshot.content); - return toVfsTextDocument(supportedDocument.withContent(snapshot.content, snapshot.lineSeparator), snapshot.isDirty(), accessContextFor(supportedDocument)); - } - - @Override - public VfsDocumentSaveResult saveDocument(final Path path) { - final var supportedDocument = requireSupportedDocument(path); - final var accessContext = accessContextFor(supportedDocument); - if (accessContext.accessMode() != VfsDocumentAccessMode.EDITABLE) { - return new VfsDocumentSaveResult(supportedDocument.path(), supportedDocument.typeId(), VfsDocumentSaveStatus.READ_ONLY); - } - final var snapshot = editableSnapshots.computeIfAbsent( - supportedDocument.path(), - ignored -> new EditableDocumentSnapshot( - supportedDocument.content(), - supportedDocument.content(), - supportedDocument.lineSeparator())); - if (!snapshot.isDirty()) { - return new VfsDocumentSaveResult(supportedDocument.path(), supportedDocument.typeId(), VfsDocumentSaveStatus.NO_CHANGES); - } - writeUtf8(supportedDocument.path(), snapshot.content); - snapshot.savedContent = snapshot.content; - snapshot.lineSeparator = lineSeparator(snapshot.content); - return new VfsDocumentSaveResult(supportedDocument.path(), supportedDocument.typeId(), VfsDocumentSaveStatus.SAVED); - } - - @Override - public VfsDocumentOpenResult.VfsTextDocument discardDocument(final Path path) { - final var supportedDocument = requireSupportedDocument(path); - editableSnapshots.remove(supportedDocument.path()); - return toVfsTextDocument(supportedDocument, false, accessContextFor(supportedDocument)); - } - - @Override - public List saveAllDocuments() { - return editableSnapshots.keySet().stream() - .map(this::saveDocument) - .toList(); - } - - private SupportedDocument requireSupportedDocument(final Path path) { - final Path normalizedPath = normalize(path); - if (!normalizedPath.startsWith(projectContext.rootPath())) { - throw new UnsupportedDocumentException(normalizedPath, VfsUnsupportedReason.OUTSIDE_PROJECT); - } - if (!Files.exists(normalizedPath)) { - throw new UnsupportedDocumentException(normalizedPath, VfsUnsupportedReason.NOT_FOUND); - } - if (!Files.isRegularFile(normalizedPath)) { - throw new UnsupportedDocumentException(normalizedPath, VfsUnsupportedReason.NOT_A_FILE); - } - - final byte[] bytes = readAllBytes(normalizedPath); - if (containsNulByte(bytes)) { - throw new UnsupportedDocumentException(normalizedPath, VfsUnsupportedReason.BINARY_CONTENT); - } - - final String content; - try { - content = StandardCharsets.UTF_8.newDecoder() - .onMalformedInput(CodingErrorAction.REPORT) - .onUnmappableCharacter(CodingErrorAction.REPORT) - .decode(ByteBuffer.wrap(bytes)) - .toString(); - } catch (CharacterCodingException codingException) { - throw new UnsupportedDocumentException(normalizedPath, VfsUnsupportedReason.INVALID_UTF8, codingException); - } - - final DocumentKind documentKind = documentKind(normalizedPath, content); - return new SupportedDocument( - normalizedPath, - normalizedPath.getFileName().toString(), - documentKind.typeId(), - documentKind.frontendDocument(), - documentKind.accessMode(), - content, - lineSeparator(content)); - } - - private VfsDocumentOpenResult openSupportedDocument(final SupportedDocument supportedDocument) { - final var accessContext = accessContextFor(supportedDocument); - if (supportedDocument.accessMode() == VfsDocumentAccessMode.EDITABLE) { - final var snapshot = editableSnapshots.computeIfAbsent( - supportedDocument.path(), - ignored -> new EditableDocumentSnapshot( - supportedDocument.content(), - supportedDocument.content(), - supportedDocument.lineSeparator())); - return toVfsTextDocument( - supportedDocument.withContent(snapshot.content, snapshot.lineSeparator), - snapshot.isDirty(), - accessContext); - } - return toVfsTextDocument(supportedDocument, false, accessContext); - } - - private VfsDocumentOpenResult.VfsTextDocument toVfsTextDocument( - final SupportedDocument supportedDocument, - final boolean dirty, - final VfsDocumentAccessContext accessContext) { - return new VfsDocumentOpenResult.VfsTextDocument( - supportedDocument.path(), - supportedDocument.documentName(), - supportedDocument.typeId(), - supportedDocument.content(), - supportedDocument.lineSeparator(), - dirty, - accessContext); - } - - private VfsProjectSnapshot buildSnapshot() { - return new VfsProjectSnapshot( - projectContext.rootPath(), - buildNode(projectContext.rootPath(), projectContext.projectName(), taggedSourceRoots())); - } - - private Set taggedSourceRoots() { - return FrontendRegistryService.getFrontendSpec(projectContext.languageId()) - .stream() - .flatMap(frontendSpec -> frontendSpec.getSourceRoots().stream()) - .map(projectContext.rootPath()::resolve) - .map(Path::toAbsolutePath) - .map(Path::normalize) - .collect(Collectors.toSet()); - } - - private DocumentKind documentKind(final Path path, final String content) { - final String extension = extensionOf(path); - if ("json".equals(extension)) { - return new DocumentKind(VfsDocumentTypeIds.JSON, false, VfsDocumentAccessMode.EDITABLE); - } - if ("ndjson".equals(extension)) { - return new DocumentKind(VfsDocumentTypeIds.NDJSON, false, VfsDocumentAccessMode.EDITABLE); - } - if (isBashDocument(path, extension, content)) { - return new DocumentKind(VfsDocumentTypeIds.BASH, false, VfsDocumentAccessMode.EDITABLE); - } - if (isFrontendSourceDocument(extension)) { - return new DocumentKind(projectContext.languageId(), true, VfsDocumentAccessMode.EDITABLE); - } - return new DocumentKind(VfsDocumentTypeIds.TEXT, false, VfsDocumentAccessMode.EDITABLE); - } - - private VfsProjectNode buildNode( - final Path path, - final String displayName, - final Set taggedRoots) { - if (!Files.isDirectory(path)) { - return new VfsProjectNode(path, displayName, false, taggedRoots.contains(path), List.of()); - } - - final List children; - try (Stream stream = Files.list(path)) { - children = stream - .sorted(nodeComparator()) - .map(child -> buildNode(child, child.getFileName().toString(), taggedRoots)) - .toList(); - } catch (IOException ioException) { - throw new UncheckedIOException(ioException); - } - - return new VfsProjectNode(path, displayName, true, taggedRoots.contains(path), children); - } - - private VfsProjectNode replaceNode(final VfsProjectNode currentNode, final VfsProjectNode replacementNode) { - if (currentNode.path().equals(replacementNode.path())) { - return replacementNode; - } - if (!replacementNode.path().startsWith(currentNode.path())) { - return currentNode; - } - if (!currentNode.directory()) { - return currentNode; - } - - final List replacedChildren = currentNode.children() - .stream() - .map(child -> replaceNode(child, replacementNode)) - .sorted(projectNodeComparator()) - .toList(); - return new VfsProjectNode( - currentNode.path(), - currentNode.displayName(), - true, - currentNode.taggedSourceRoot(), - replacedChildren); - } - - private Path refreshRootFor(final Path targetPath) { - final Path normalizedTarget = normalize(targetPath); - if (!normalizedTarget.startsWith(projectContext.rootPath())) { - throw new IllegalArgumentException("Refresh target must stay within the project root."); - } - if (Files.exists(normalizedTarget)) { - return normalizedTarget; - } - final Path parent = normalizedTarget.getParent(); - if (parent == null || !parent.startsWith(projectContext.rootPath())) { - return projectContext.rootPath(); - } - return parent; - } - - private Comparator nodeComparator() { - return Comparator - .comparing((Path path) -> !Files.isDirectory(path)) - .thenComparing(path -> path.getFileName().toString(), String.CASE_INSENSITIVE_ORDER); - } - - private Comparator projectNodeComparator() { - return Comparator - .comparing((VfsProjectNode node) -> !node.directory()) - .thenComparing(VfsProjectNode::displayName, String.CASE_INSENSITIVE_ORDER); - } - - private Path normalize(final Path path) { - return Objects.requireNonNull(path, "path").toAbsolutePath().normalize(); - } - - private boolean isFrontendSourceDocument(final String extension) { - if (extension.isBlank()) { - return false; - } - return FrontendRegistryService.getFrontendSpec(projectContext.languageId()) - .map(FrontendSpec::getAllowedExtensions) - .stream() - .flatMap(allowedExtensions -> allowedExtensions.stream()) - .anyMatch(allowedExtension -> allowedExtension.equalsIgnoreCase(extension)); - } - - private boolean isBashDocument(final Path path, final String extension, final String content) { - if (Set.of("sh", "bash", "bashrc", "bash_profile").contains(extension)) { - return true; - } - final String fileName = path.getFileName().toString().toLowerCase(Locale.ROOT); - if (".bashrc".equals(fileName) || ".bash_profile".equals(fileName)) { - return true; - } - final int firstLineBreak = content.indexOf('\n'); - final String firstLine = firstLineBreak >= 0 ? content.substring(0, firstLineBreak) : content; - return firstLine.startsWith("#!") && (firstLine.contains("bash") || firstLine.contains("/sh")); - } - - private String extensionOf(final Path path) { - final String fileName = path.getFileName().toString(); - final int dot = fileName.lastIndexOf('.'); - if (dot < 0 || dot == fileName.length() - 1) { - return ""; - } - return fileName.substring(dot + 1).toLowerCase(Locale.ROOT); - } - - private boolean containsNulByte(final byte[] bytes) { - for (final byte value : bytes) { - if (value == 0) { - return true; - } - } - return false; - } - - private String lineSeparator(final String content) { - return content.contains("\r\n") ? "CRLF" : "LF"; - } - - private byte[] readAllBytes(final Path path) { - try { - return Files.readAllBytes(path); - } catch (IOException ioException) { - throw new UncheckedIOException(ioException); - } - } - - private void writeUtf8(final Path path, final String content) { - try { - Files.writeString(path, content, StandardCharsets.UTF_8); - } catch (IOException ioException) { - throw new UncheckedIOException(ioException); - } - } - - private VfsDocumentAccessContext accessContextFor(final SupportedDocument supportedDocument) { - final var attributes = accessContextAttributes.computeIfAbsent(supportedDocument.path(), ignored -> Map.of()); - return new VfsDocumentAccessContext( - supportedDocument.path(), - supportedDocument.typeId(), - supportedDocument.frontendDocument(), - supportedDocument.accessMode(), - attributes); - } - - private record DocumentKind( - String typeId, - boolean frontendDocument, - VfsDocumentAccessMode accessMode) { - } - - private record SupportedDocument( - Path path, - String documentName, - String typeId, - boolean frontendDocument, - VfsDocumentAccessMode accessMode, - String content, - String lineSeparator) { - - private SupportedDocument withContent(final String updatedContent, final String updatedLineSeparator) { - return new SupportedDocument( - path, - documentName, - typeId, - frontendDocument, - accessMode, - updatedContent, - updatedLineSeparator); - } - } - - private static final class EditableDocumentSnapshot { - private String savedContent; - private String content; - private String lineSeparator; - - private EditableDocumentSnapshot( - final String savedContent, - final String content, - final String lineSeparator) { - this.savedContent = savedContent; - this.content = content; - this.lineSeparator = lineSeparator; - } - - private boolean isDirty() { - return !Objects.equals(savedContent, content); - } - } - - private static final class UnsupportedDocumentException extends IllegalArgumentException { - private final Path path; - private final VfsUnsupportedReason reason; - - private UnsupportedDocumentException(final Path path, final VfsUnsupportedReason reason) { - super(reason.name() + ": " + path); - this.path = path; - this.reason = reason; - } - - private UnsupportedDocumentException( - final Path path, - final VfsUnsupportedReason reason, - final Throwable cause) { - super(reason.name() + ": " + path, cause); - this.path = path; - this.reason = reason; - } - - private Path path() { - return path; - } - - private VfsUnsupportedReason reason() { - return reason; - } - } -} diff --git a/prometeu-vfs/prometeu-vfs-v1/src/test/java/p/studio/vfs/FilesystemVfsProjectDocumentTest.java b/prometeu-vfs/prometeu-vfs-v1/src/test/java/p/studio/vfs/FilesystemVfsProjectDocumentTest.java deleted file mode 100644 index f619f924..00000000 --- a/prometeu-vfs/prometeu-vfs-v1/src/test/java/p/studio/vfs/FilesystemVfsProjectDocumentTest.java +++ /dev/null @@ -1,237 +0,0 @@ -package p.studio.vfs; - -import org.junit.jupiter.api.Test; -import org.junit.jupiter.api.io.TempDir; -import p.studio.vfs.messages.*; - -import java.nio.file.Files; -import java.nio.file.Path; -import java.util.Map; - -import static org.junit.jupiter.api.Assertions.*; - -final class FilesystemVfsProjectDocumentTest { - @TempDir - Path tempDir; - - @Test - void snapshotIncludesHiddenFilesOrdersFoldersFirstAndTagsSourceRoots() throws Exception { - Files.createDirectories(tempDir.resolve("src")); - Files.createDirectories(tempDir.resolve("assets")); - Files.writeString(tempDir.resolve(".env"), "TOKEN=1\n"); - Files.writeString(tempDir.resolve("README.md"), "# project\n"); - - final VfsProjectDocument vfs = new FilesystemProjectDocumentVfsFactory().open(projectContext()); - - final VfsProjectSnapshot snapshot = vfs.snapshot(); - - assertEquals("Example", snapshot.rootNode().displayName()); - assertEquals("assets", snapshot.rootNode().children().get(0).displayName()); - assertEquals("src", snapshot.rootNode().children().get(1).displayName()); - assertEquals(".env", snapshot.rootNode().children().get(2).displayName()); - assertTrue(snapshot.rootNode().children().get(1).taggedSourceRoot()); - } - - @Test - void openDocumentReturnsTextDocumentForUtf8TextFile() throws Exception { - final Path file = tempDir.resolve("main.pbs"); - Files.writeString(file, "fn main(): void\n"); - - final VfsProjectDocument vfs = new FilesystemProjectDocumentVfsFactory().open(projectContext()); - - final VfsDocumentOpenResult result = vfs.openDocument(file); - final var document = assertInstanceOf(VfsDocumentOpenResult.VfsTextDocument.class, result); - - assertEquals("main.pbs", document.documentName()); - assertEquals("pbs", document.typeId()); - assertEquals("LF", document.lineSeparator()); - assertEquals(VfsDocumentAccessMode.EDITABLE, document.accessContext().accessMode()); - assertTrue(document.accessContext().frontendDocument()); - assertTrue(document.content().contains("fn main()")); - } - - @Test - void openDocumentClassifiesJsonFilesWithJsonTypeIdentifier() throws Exception { - final Path file = tempDir.resolve("prometeu.json"); - Files.writeString(file, "{\n \"name\": \"Example\"\n}\n"); - - final VfsProjectDocument vfs = new FilesystemProjectDocumentVfsFactory().open(projectContext()); - - final VfsDocumentOpenResult result = vfs.openDocument(file); - final var document = assertInstanceOf(VfsDocumentOpenResult.VfsTextDocument.class, result); - - assertEquals(VfsDocumentTypeIds.JSON, document.typeId()); - assertEquals(VfsDocumentAccessMode.EDITABLE, document.accessContext().accessMode()); - } - - @Test - void openDocumentClassifiesNdjsonFilesWithJsonTypeIdentifier() throws Exception { - final Path file = tempDir.resolve("events.ndjson"); - Files.writeString(file, "{\"event\":\"start\"}\n{\"event\":\"done\"}\n"); - - final VfsProjectDocument vfs = new FilesystemProjectDocumentVfsFactory().open(projectContext()); - - final VfsDocumentOpenResult result = vfs.openDocument(file); - final var document = assertInstanceOf(VfsDocumentOpenResult.VfsTextDocument.class, result); - - assertEquals(VfsDocumentTypeIds.NDJSON, document.typeId()); - } - - @Test - void openDocumentClassifiesBashScriptsWithBashTypeIdentifier() throws Exception { - final Path file = tempDir.resolve("script.sh"); - Files.writeString(file, "#!/usr/bin/env bash\nprintf \"hi\"\n"); - - final VfsProjectDocument vfs = new FilesystemProjectDocumentVfsFactory().open(projectContext()); - - final VfsDocumentOpenResult result = vfs.openDocument(file); - final var document = assertInstanceOf(VfsDocumentOpenResult.VfsTextDocument.class, result); - - assertEquals(VfsDocumentTypeIds.BASH, document.typeId()); - assertEquals(VfsDocumentAccessMode.EDITABLE, document.accessContext().accessMode()); - } - - @Test - void frontendDocumentsUseEditableInMemorySnapshotsUntilSavePersistsThem() throws Exception { - final Path file = tempDir.resolve("main.pbs"); - Files.writeString(file, "fn main(): void\n"); - - final VfsProjectDocument vfs = new FilesystemProjectDocumentVfsFactory().open(projectContext()); - final var updated = vfs.updateDocument(file, "fn main(): int\n"); - - assertTrue(updated.dirty()); - assertEquals("fn main(): int\n", updated.content()); - assertEquals("fn main(): void\n", Files.readString(file)); - assertEquals("fn main(): int\n", assertInstanceOf(VfsDocumentOpenResult.VfsTextDocument.class, vfs.openDocument(file)).content()); - - final VfsDocumentSaveResult saveResult = vfs.saveDocument(file); - - assertEquals(VfsDocumentSaveStatus.SAVED, saveResult.status()); - assertEquals("fn main(): int\n", Files.readString(file)); - assertFalse(assertInstanceOf(VfsDocumentOpenResult.VfsTextDocument.class, vfs.openDocument(file)).dirty()); - } - - @Test - void editableDocumentsUseInMemorySnapshotsUntilSavePersistsThem() throws Exception { - final Path file = tempDir.resolve("notes.txt"); - Files.writeString(file, "alpha\n"); - - final VfsProjectDocument vfs = new FilesystemProjectDocumentVfsFactory().open(projectContext()); - - final var updated = vfs.updateDocument(file, "beta\n"); - - assertTrue(updated.dirty()); - assertEquals("beta\n", updated.content()); - assertEquals("alpha\n", Files.readString(file)); - assertEquals("beta\n", assertInstanceOf(VfsDocumentOpenResult.VfsTextDocument.class, vfs.openDocument(file)).content()); - - final VfsDocumentSaveResult saveResult = vfs.saveDocument(file); - - assertEquals(VfsDocumentSaveStatus.SAVED, saveResult.status()); - assertEquals("beta\n", Files.readString(file)); - assertFalse(assertInstanceOf(VfsDocumentOpenResult.VfsTextDocument.class, vfs.openDocument(file)).dirty()); - } - - @Test - void discardDocumentDropsDirtySnapshotAndRestoresFilesystemState() throws Exception { - final Path file = tempDir.resolve("notes.txt"); - Files.writeString(file, "alpha\n"); - - final VfsProjectDocument vfs = new FilesystemProjectDocumentVfsFactory().open(projectContext()); - vfs.updateDocument(file, "beta\n"); - - final var discarded = vfs.discardDocument(file); - - assertFalse(discarded.dirty()); - assertEquals("alpha\n", discarded.content()); - assertEquals("alpha\n", Files.readString(file)); - assertEquals("alpha\n", assertInstanceOf(VfsDocumentOpenResult.VfsTextDocument.class, vfs.openDocument(file)).content()); - } - - @Test - void saveAllDocumentsPersistsEditableDirtySnapshotsIncludingFrontendDocuments() throws Exception { - final Path editable = tempDir.resolve("notes.txt"); - final Path frontend = tempDir.resolve("main.pbs"); - Files.writeString(editable, "alpha\n"); - Files.writeString(frontend, "fn main(): void\n"); - - final VfsProjectDocument vfs = new FilesystemProjectDocumentVfsFactory().open(projectContext()); - vfs.updateDocument(editable, "beta\n"); - vfs.updateDocument(frontend, "fn main(): int\n"); - - final var results = vfs.saveAllDocuments(); - - assertEquals(2, results.size()); - assertEquals(editable.toAbsolutePath().normalize(), results.get(0).path()); - assertEquals(VfsDocumentSaveStatus.SAVED, results.get(0).status()); - assertEquals(frontend.toAbsolutePath().normalize(), results.get(1).path()); - assertEquals(VfsDocumentSaveStatus.SAVED, results.get(1).status()); - assertEquals("beta\n", Files.readString(editable)); - assertEquals("fn main(): int\n", Files.readString(frontend)); - } - - @Test - void accessContextCanBeReadAndMutatedWithoutChangingCanonicalPolicy() throws Exception { - final Path file = tempDir.resolve("prometeu.json"); - Files.writeString(file, "{\n \"name\": \"Example\"\n}\n"); - - final VfsProjectDocument vfs = new FilesystemProjectDocumentVfsFactory().open(projectContext()); - - final VfsDocumentAccessContext initialContext = vfs.accessContext(file); - final VfsDocumentAccessContext updatedContext = vfs.updateAccessContext(file, Map.of("statusBar", "future-toggle")); - - assertEquals(VfsDocumentAccessMode.EDITABLE, initialContext.accessMode()); - assertEquals(VfsDocumentTypeIds.JSON, initialContext.typeId()); - assertEquals(Map.of("statusBar", "future-toggle"), updatedContext.attributes()); - assertEquals(initialContext.accessMode(), updatedContext.accessMode()); - assertEquals(initialContext.typeId(), updatedContext.typeId()); - } - - @Test - void openDocumentRejectsBinaryLikeFiles() throws Exception { - final Path file = tempDir.resolve("sprite.bin"); - Files.write(file, new byte[]{0x01, 0x00, 0x02}); - - final VfsProjectDocument vfs = new FilesystemProjectDocumentVfsFactory().open(projectContext()); - - final VfsDocumentOpenResult result = vfs.openDocument(file); - final var unsupported = assertInstanceOf(VfsDocumentOpenResult.VfsUnsupportedDocument.class, result); - - assertEquals(VfsUnsupportedReason.BINARY_CONTENT, unsupported.reason()); - } - - @Test - void openDocumentRejectsPathsOutsideProjectScope() throws Exception { - final Path outsideFile = tempDir.getParent().resolve("outside.pbs"); - Files.writeString(outsideFile, "fn stray(): void\n"); - - final VfsProjectDocument vfs = new FilesystemProjectDocumentVfsFactory().open(projectContext()); - - final VfsDocumentOpenResult result = vfs.openDocument(outsideFile); - final var unsupported = assertInstanceOf(VfsDocumentOpenResult.VfsUnsupportedDocument.class, result); - - assertEquals(VfsUnsupportedReason.OUTSIDE_PROJECT, unsupported.reason()); - } - - @Test - void targetedRefreshUpdatesOnlyTheRequestedSubtreeInTheSnapshot() throws Exception { - final Path src = Files.createDirectories(tempDir.resolve("src")); - Files.createDirectories(tempDir.resolve("assets")); - Files.writeString(src.resolve("main.pbs"), "fn main(): void\n"); - - final VfsProjectDocument vfs = new FilesystemProjectDocumentVfsFactory().open(projectContext()); - Files.writeString(src.resolve("later.pbs"), "fn later(): void\n"); - - final VfsProjectSnapshot refreshedSnapshot = vfs.refresh(new VfsRefreshRequest(src)); - final VfsProjectNode srcNode = refreshedSnapshot.rootNode().children().get(1); - - assertEquals("src", srcNode.displayName()); - assertEquals(2, srcNode.children().size()); - assertEquals("later.pbs", srcNode.children().get(0).displayName()); - assertEquals("main.pbs", srcNode.children().get(1).displayName()); - } - - private VfsProjectContext projectContext() { - return new VfsProjectContext("Example", "pbs", tempDir); - } -} diff --git a/settings.gradle.kts b/settings.gradle.kts index 0df55951..dc36dbbc 100644 --- a/settings.gradle.kts +++ b/settings.gradle.kts @@ -5,10 +5,6 @@ plugins { rootProject.name = "prometeu-studio" include("prometeu-infra") -include("prometeu-vfs:prometeu-vfs-api") -include("prometeu-vfs:prometeu-vfs-v1") -include("prometeu-lsp:prometeu-lsp-api") -include("prometeu-lsp:prometeu-lsp-v1") include("prometeu-packer:prometeu-packer-api") include("prometeu-packer:prometeu-packer-v1") -- 2.47.2 From 6b60fa9d3301420863e808861658858ba8485fe9 Mon Sep 17 00:00:00 2001 From: bQUARKz Date: Tue, 5 May 2026 11:20:09 +0100 Subject: [PATCH 03/37] implements PLN-0064 --- README.md | 11 +- discussion/index.ndjson | 2 +- ...ditor-foundations-and-semantic-deferral.md | 4 + ...t-vfs-and-session-owned-editor-boundary.md | 4 + ...e-and-read-only-frontend-semantic-phase.md | 4 + ...ntation-descriptor-and-host-consumption.md | 4 + ...r-and-frontend-owned-structural-anchors.md | 4 + ...-hints-with-decorative-inline-rendering.md | 4 + ...n-policy-and-project-bootstrap-defaults.md | 4 + ...6-vfs-owned-frontend-edit-and-save-wave.md | 4 + ...lesson-cleanup-for-editor-stack-removal.md | 15 +- ...hell and Workspace Layout Specification.md | 7 +- .../5. Code Editor Workspace Specification.md | 377 ---------- .../6. Project Document VFS Specification.md | 235 ------- ...d LSP Semantic Read Phase Specification.md | 183 ----- ...roject-Local Studio State Specification.md | 11 +- docs/specs/studio/README.md | 20 +- .../java/p/studio/utilities/i18n/I18n.java | 32 - .../main/resources/i18n/messages.properties | 33 +- .../resources/i18n/messages_pt_BR.properties | 1 - .../resources/themes/default-prometeu.css | 664 ------------------ .../themes/editor/presentations/bash.css | 39 - .../themes/editor/presentations/json.css | 41 -- 23 files changed, 56 insertions(+), 1647 deletions(-) delete mode 100644 docs/specs/studio/5. Code Editor Workspace Specification.md delete mode 100644 docs/specs/studio/6. Project Document VFS Specification.md delete mode 100644 docs/specs/studio/7. Integrated LSP Semantic Read Phase Specification.md delete mode 100644 prometeu-studio/src/main/resources/themes/editor/presentations/bash.css delete mode 100644 prometeu-studio/src/main/resources/themes/editor/presentations/json.css diff --git a/README.md b/README.md index a3b6427a..748f1020 100644 --- a/README.md +++ b/README.md @@ -2,7 +2,7 @@ Prometeu Studio is the desktop development environment for the Prometeu toolchain. -This repository packages the Studio shell together with the embedded services it depends on: project VFS, language tooling, compiler pipeline integration, and asset packing. The current implementation is a Java/JavaFX multi-module Gradle build. +This repository packages the Studio shell together with the embedded services it depends on: compiler pipeline integration, asset packing, runtime/debug orchestration, and project-local Studio state. The current implementation is a Java/JavaFX multi-module Gradle build. ## What Lives Here @@ -10,8 +10,6 @@ The root project is a monorepo with these main areas: - `prometeu-app`: JavaFX application entry point (`p.studio.App`). - `prometeu-studio`: Studio UI, workspaces, project session lifecycle, play/stop flow, and debugger-facing surfaces. -- `prometeu-vfs`: project document access and save/open contracts. -- `prometeu-lsp`: language-service integration used by the editor workflow. - `prometeu-packer`: embedded packer APIs and implementation used by Studio. - `prometeu-compiler`: compiler core, build pipeline, frontend APIs, and the PBS frontend. - `prometeu-infra`: shared infrastructure used across modules. @@ -21,14 +19,13 @@ The root project is a monorepo with these main areas: ## Current Product Shape -The Studio shell currently organizes the product around four workspaces: +The Studio shell currently organizes the product around three workspaces: - Assets -- Code editor - Debug - Shipper -At runtime, the app boots an embedded packer, creates a project document VFS, wires LSP services, and opens the Studio launcher window. Project creation currently scaffolds a Prometeu workspace with `prometeu.json`, `src/`, `assets/`, `build/`, `cartridge/`, `.workspace/`, and local Studio metadata. +At runtime, the app boots an embedded packer, restores project-local Studio state, and opens the Studio launcher window. Project creation currently scaffolds a Prometeu workspace with `prometeu.json`, `src/`, `assets/`, `build/`, `cartridge/`, `.workspace/`, and local Studio metadata. ## Requirements @@ -68,7 +65,7 @@ If you are new to the codebase, this order is usually the fastest path: 1. Start at `prometeu-app` to see application bootstrap. 2. Read `prometeu-studio` for the shell, workspaces, and user-facing flows. -3. Read `prometeu-vfs`, `prometeu-lsp`, and `prometeu-packer` for service boundaries. +3. Read `prometeu-packer` for asset and packaging boundaries. 4. Read `prometeu-compiler` when you need compiler or PBS language behavior. ## Specs And Architecture diff --git a/discussion/index.ndjson b/discussion/index.ndjson index 0b06bb11..038eb391 100644 --- a/discussion/index.ndjson +++ b/discussion/index.ndjson @@ -1,5 +1,5 @@ {"type":"meta","next_id":{"DSC":32,"AGD":35,"DEC":32,"PLN":65,"LSN":47,"CLSN":1}} -{"type":"discussion","id":"DSC-0031","status":"in_progress","ticket":"studio-editor-workspace-cleanup","title":"Limpeza completa do Workspace Editor do Studio e remoção dos acoplamentos legados","created_at":"2026-05-05","updated_at":"2026-05-05","tags":["studio","editor","cleanup","vfs","lsp","migration"],"agendas":[{"id":"AGD-0034","file":"AGD-0034-vscode-editor-migration-feasibility.md","status":"accepted","created_at":"2026-05-05","updated_at":"2026-05-05"}],"decisions":[{"id":"DEC-0031","file":"DEC-0031-studio-editor-workspace-cleanup.md","status":"in_progress","created_at":"2026-05-05","updated_at":"2026-05-05","ref_agenda":"AGD-0034"}],"plans":[{"id":"PLN-0062","file":"PLN-0062-shell-session-and-state-cleanup-after-editor-removal.md","status":"done","created_at":"2026-05-05","updated_at":"2026-05-05","ref_decisions":["DEC-0031"]},{"id":"PLN-0063","file":"PLN-0063-legacy-lsp-and-vfs-module-removal-with-runtime-preservation.md","status":"done","created_at":"2026-05-05","updated_at":"2026-05-05","ref_decisions":["DEC-0031"]},{"id":"PLN-0064","file":"PLN-0064-normative-test-and-lesson-cleanup-for-editor-stack-removal.md","status":"open","created_at":"2026-05-05","updated_at":"2026-05-05","ref_decisions":["DEC-0031"]}],"lessons":[]} +{"type":"discussion","id":"DSC-0031","status":"in_progress","ticket":"studio-editor-workspace-cleanup","title":"Limpeza completa do Workspace Editor do Studio e remoção dos acoplamentos legados","created_at":"2026-05-05","updated_at":"2026-05-05","tags":["studio","editor","cleanup","vfs","lsp","migration"],"agendas":[{"id":"AGD-0034","file":"AGD-0034-vscode-editor-migration-feasibility.md","status":"accepted","created_at":"2026-05-05","updated_at":"2026-05-05"}],"decisions":[{"id":"DEC-0031","file":"DEC-0031-studio-editor-workspace-cleanup.md","status":"in_progress","created_at":"2026-05-05","updated_at":"2026-05-05","ref_agenda":"AGD-0034"}],"plans":[{"id":"PLN-0062","file":"PLN-0062-shell-session-and-state-cleanup-after-editor-removal.md","status":"done","created_at":"2026-05-05","updated_at":"2026-05-05","ref_decisions":["DEC-0031"]},{"id":"PLN-0063","file":"PLN-0063-legacy-lsp-and-vfs-module-removal-with-runtime-preservation.md","status":"done","created_at":"2026-05-05","updated_at":"2026-05-05","ref_decisions":["DEC-0031"]},{"id":"PLN-0064","file":"PLN-0064-normative-test-and-lesson-cleanup-for-editor-stack-removal.md","status":"done","created_at":"2026-05-05","updated_at":"2026-05-05","ref_decisions":["DEC-0031"]}],"lessons":[]} {"type":"discussion","id":"DSC-0030","status":"done","ticket":"studio-scene-pack-runtime-binary-contract","title":"Studio scene pack contract for runtime SCENE binary payload","created_at":"2026-04-24","updated_at":"2026-05-01","tags":["studio","packer","runtime","scene","asset-pack","binary-format","tiled"],"agendas":[],"decisions":[],"plans":[],"lessons":[{"id":"LSN-0046","file":"discussion/lessons/DSC-0030-studio-scene-pack-runtime-binary-contract/LSN-0046-canonical-scene-owns-editorial-truth-while-pack-stays-request-driven.md","status":"done","created_at":"2026-05-01","updated_at":"2026-05-01"}]} {"type":"discussion","id":"DSC-0029","status":"done","ticket":"studio-frame-composer-syscall-and-sprite-alignment","title":"Studio Alignment with Runtime FrameComposer Syscalls and Sprite Composition","created_at":"2026-04-18","updated_at":"2026-04-18","tags":["studio","compiler","pbs","stdlib","runtime-alignment","abi","syscall","frame-composer","sprites"],"agendas":[],"decisions":[],"plans":[],"lessons":[{"id":"LSN-0041","file":"discussion/lessons/DSC-0029-studio-frame-composer-syscall-and-sprite-alignment/LSN-0041-composer-must-own-public-sprite-composition.md","status":"done","created_at":"2026-04-18","updated_at":"2026-04-18"}]} {"type":"discussion","id":"DSC-0028","status":"done","ticket":"studio-tiled-parser-assets-scene-asset-type","title":"Tiled Parser and Scene Asset-Type Ownership in Assets Workspace","created_at":"2026-04-15","updated_at":"2026-04-23","tags":["studio","assets","scene","tiled","parser","asset-type"],"agendas":[],"decisions":[],"plans":[],"lessons":[{"id":"LSN-0045","file":"discussion/lessons/DSC-0028-studio-tiled-parser-assets-scene-asset-type/LSN-0045-asset-owned-scene-bank-and-tiled-xml-workflow.md","status":"done","created_at":"2026-04-23","updated_at":"2026-04-23"}]} diff --git a/discussion/lessons/DSC-0010-studio-code-editor-workspace-foundations/LSN-0026-read-only-editor-foundations-and-semantic-deferral.md b/discussion/lessons/DSC-0010-studio-code-editor-workspace-foundations/LSN-0026-read-only-editor-foundations-and-semantic-deferral.md index 6fb7d673..59ff60de 100644 --- a/discussion/lessons/DSC-0010-studio-code-editor-workspace-foundations/LSN-0026-read-only-editor-foundations-and-semantic-deferral.md +++ b/discussion/lessons/DSC-0010-studio-code-editor-workspace-foundations/LSN-0026-read-only-editor-foundations-and-semantic-deferral.md @@ -6,6 +6,10 @@ created: 2026-03-31 tags: [studio, editor, workspace, read-only, navigator, tabs, lsp-deferred, ui-foundations] --- +## Historical Status + +This lesson documents the removed embedded Studio code editor. Keep it as historical context only; do not treat it as current product guidance after `DEC-0031`. + ## Context Studio needed a real `Code Editor` workspace, but the team explicitly did not want the first wave to collapse UI structure, file management, write behavior, and language semantics into one premature implementation. diff --git a/discussion/lessons/DSC-0012-studio-editor-document-vfs-boundary/LSN-0027-project-document-vfs-and-session-owned-editor-boundary.md b/discussion/lessons/DSC-0012-studio-editor-document-vfs-boundary/LSN-0027-project-document-vfs-and-session-owned-editor-boundary.md index 12253223..02548f45 100644 --- a/discussion/lessons/DSC-0012-studio-editor-document-vfs-boundary/LSN-0027-project-document-vfs-and-session-owned-editor-boundary.md +++ b/discussion/lessons/DSC-0012-studio-editor-document-vfs-boundary/LSN-0027-project-document-vfs-and-session-owned-editor-boundary.md @@ -6,6 +6,10 @@ created: 2026-03-31 tags: [studio, editor, vfs, project-session, filesystem, boundary, architecture] --- +## Historical Status + +This lesson documents the removed embedded Studio editor/VFS split. Keep it as historical context only; do not treat it as current product guidance after `DEC-0031`. + ## Context The first Studio `Code Editor` wave had already established a read-only editorial shell, but the concrete implementation still let the editor package own direct filesystem concerns for: diff --git a/discussion/lessons/DSC-0013-studio-editor-write-wave-supported-non-frontend-files/LSN-0028-controlled-editor-write-wave-and-read-only-frontend-semantic-phase.md b/discussion/lessons/DSC-0013-studio-editor-write-wave-supported-non-frontend-files/LSN-0028-controlled-editor-write-wave-and-read-only-frontend-semantic-phase.md index 5d1af977..fd1ac79b 100644 --- a/discussion/lessons/DSC-0013-studio-editor-write-wave-supported-non-frontend-files/LSN-0028-controlled-editor-write-wave-and-read-only-frontend-semantic-phase.md +++ b/discussion/lessons/DSC-0013-studio-editor-write-wave-supported-non-frontend-files/LSN-0028-controlled-editor-write-wave-and-read-only-frontend-semantic-phase.md @@ -6,6 +6,10 @@ created: 2026-04-02 tags: [studio, editor, vfs, lsp, access-policy, save, read-only, frontend-boundary] --- +## Historical Status + +This lesson documents the removed embedded Studio editor, VFS, and legacy LSP flow. Keep it as historical context only; do not treat it as current product guidance after `DEC-0031`. + ## Context The first Studio `Code Editor` implementation had already established a session-owned document boundary through `prometeu-vfs`, but it was still missing the next operational split: diff --git a/discussion/lessons/DSC-0014-studio-frontend-owned-semantic-editor-presentation/LSN-0029-frontend-owned-semantic-presentation-descriptor-and-host-consumption.md b/discussion/lessons/DSC-0014-studio-frontend-owned-semantic-editor-presentation/LSN-0029-frontend-owned-semantic-presentation-descriptor-and-host-consumption.md index 08b8eaaa..e696df55 100644 --- a/discussion/lessons/DSC-0014-studio-frontend-owned-semantic-editor-presentation/LSN-0029-frontend-owned-semantic-presentation-descriptor-and-host-consumption.md +++ b/discussion/lessons/DSC-0014-studio-frontend-owned-semantic-editor-presentation/LSN-0029-frontend-owned-semantic-presentation-descriptor-and-host-consumption.md @@ -6,6 +6,10 @@ created: 2026-04-02 tags: [studio, editor, frontend, semantic-highlighting, lsp, compiler, pbs, presentation] --- +## Historical Status + +This lesson documents the removed embedded Studio semantic editor presentation path. Keep it as historical context only; do not treat it as current product guidance after `DEC-0031`. + ## Context The first semantic highlight wave for frontend documents had already proved that Studio could consume semantic spans through the integrated LSP path. diff --git a/discussion/lessons/DSC-0016-studio-editor-scope-guides-and-brace-anchoring/LSN-0034-active-scope-gutter-and-frontend-owned-structural-anchors.md b/discussion/lessons/DSC-0016-studio-editor-scope-guides-and-brace-anchoring/LSN-0034-active-scope-gutter-and-frontend-owned-structural-anchors.md index 6fef5de8..3dc30133 100644 --- a/discussion/lessons/DSC-0016-studio-editor-scope-guides-and-brace-anchoring/LSN-0034-active-scope-gutter-and-frontend-owned-structural-anchors.md +++ b/discussion/lessons/DSC-0016-studio-editor-scope-guides-and-brace-anchoring/LSN-0034-active-scope-gutter-and-frontend-owned-structural-anchors.md @@ -6,6 +6,10 @@ created: 2026-04-06 tags: [studio, editor, scope-guides, structural-anchors, semantic-read, frontend-contract] --- +## Historical Status + +This lesson documents the removed embedded Studio editor gutter and structural-anchor flow. Keep it as historical context only; do not treat it as current product guidance after `DEC-0031`. + ## Context The Studio editor already exposed structural guides in the gutter, but the old behavior mixed two different concerns: diff --git a/discussion/lessons/DSC-0017-studio-editor-inline-type-hints-for-let-bindings/LSN-0035-frontend-owned-inline-hints-with-decorative-inline-rendering.md b/discussion/lessons/DSC-0017-studio-editor-inline-type-hints-for-let-bindings/LSN-0035-frontend-owned-inline-hints-with-decorative-inline-rendering.md index 6148aa40..28c9df00 100644 --- a/discussion/lessons/DSC-0017-studio-editor-inline-type-hints-for-let-bindings/LSN-0035-frontend-owned-inline-hints-with-decorative-inline-rendering.md +++ b/discussion/lessons/DSC-0017-studio-editor-inline-type-hints-for-let-bindings/LSN-0035-frontend-owned-inline-hints-with-decorative-inline-rendering.md @@ -6,6 +6,10 @@ created: 2026-04-06 tags: [studio, editor, inline-hints, lsp, compiler, pbs, type-inference, rendering] --- +## Historical Status + +This lesson documents the removed embedded Studio inline-hint path. Keep it as historical context only; do not treat it as current product guidance after `DEC-0031`. + ## Context The repository needed inline type hints for inferred PBS `let` bindings, but the real architectural issue was broader than one PBS feature. diff --git a/discussion/lessons/DSC-0020-studio-editor-indentation-policy-and-project-setup/LSN-0033-setup-owned-indentation-policy-and-project-bootstrap-defaults.md b/discussion/lessons/DSC-0020-studio-editor-indentation-policy-and-project-setup/LSN-0033-setup-owned-indentation-policy-and-project-bootstrap-defaults.md index faa8ecc2..0167ed5c 100644 --- a/discussion/lessons/DSC-0020-studio-editor-indentation-policy-and-project-setup/LSN-0033-setup-owned-indentation-policy-and-project-bootstrap-defaults.md +++ b/discussion/lessons/DSC-0020-studio-editor-indentation-policy-and-project-setup/LSN-0033-setup-owned-indentation-policy-and-project-bootstrap-defaults.md @@ -6,6 +6,10 @@ created: 2026-04-04 tags: [studio, editor, indentation, tabs, setup, dot-studio, project-creation, gitignore] --- +## Historical Status + +This lesson documents indentation policy choices made for the removed embedded Studio editor. Keep it as historical context only; do not treat it as current product guidance after `DEC-0031`. + ## Context The Studio editor exposed an indentation chip in the status bar, but that chip was driven by file-content heuristics rather than by a stable editor policy. diff --git a/discussion/lessons/DSC-0021-studio-frontend-editor-write-and-save-wave/LSN-0036-vfs-owned-frontend-edit-and-save-wave.md b/discussion/lessons/DSC-0021-studio-frontend-editor-write-and-save-wave/LSN-0036-vfs-owned-frontend-edit-and-save-wave.md index 15045bb1..10ae674c 100644 --- a/discussion/lessons/DSC-0021-studio-frontend-editor-write-and-save-wave/LSN-0036-vfs-owned-frontend-edit-and-save-wave.md +++ b/discussion/lessons/DSC-0021-studio-frontend-editor-write-and-save-wave/LSN-0036-vfs-owned-frontend-edit-and-save-wave.md @@ -6,6 +6,10 @@ created: 2026-04-06 tags: [studio, editor, frontend, write, save, vfs, lsp, access-policy, persistence] --- +## Historical Status + +This lesson documents the removed embedded Studio frontend edit/save wave. Keep it as historical context only; do not treat it as current product guidance after `DEC-0031`. + ## Context The first editor write wave had deliberately kept frontend files hard `read-only` while semantic-read support shipped through `prometeu-lsp`. diff --git a/discussion/workflow/plans/PLN-0064-normative-test-and-lesson-cleanup-for-editor-stack-removal.md b/discussion/workflow/plans/PLN-0064-normative-test-and-lesson-cleanup-for-editor-stack-removal.md index 1572f13a..bf0bdd81 100644 --- a/discussion/workflow/plans/PLN-0064-normative-test-and-lesson-cleanup-for-editor-stack-removal.md +++ b/discussion/workflow/plans/PLN-0064-normative-test-and-lesson-cleanup-for-editor-stack-removal.md @@ -2,9 +2,9 @@ id: PLN-0064 ticket: studio-editor-workspace-cleanup title: Normative Test and Lesson Cleanup for Editor Stack Removal -status: open +status: done created: 2026-05-05 -completed: +completed: 2026-05-05 tags: [studio, editor, cleanup, docs, tests, lessons] --- @@ -72,11 +72,11 @@ Remove or revise the normative documentation, tests, lessons, and user-facing re ## Acceptance Criteria -- [ ] Studio specs no longer define the embedded editor stack as an active surface. -- [ ] Studio README/index material no longer points to removed editor/VFS/LSP architecture as current. -- [ ] Editor-specific i18n keys are removed or no longer consumed. -- [ ] Obsolete tests are removed or rewritten. -- [ ] Historical lessons are clearly demoted from active operational guidance. +- [x] Studio specs no longer define the embedded editor stack as an active surface. +- [x] Studio README/index material no longer points to removed editor/VFS/LSP architecture as current. +- [x] Editor-specific i18n keys are removed or no longer consumed. +- [x] Obsolete tests are removed or rewritten. +- [x] Historical lessons are clearly demoted from active operational guidance. ## Dependencies @@ -88,4 +88,3 @@ Remove or revise the normative documentation, tests, lessons, and user-facing re - Removing normative docs too early may temporarily leave the repo without clear current guidance. - Historical lessons may still be valuable; deleting them outright could lose context that should instead be reclassified. - Partial cleanup can leave broken links or missing i18n keys that only appear at runtime. - diff --git a/docs/specs/studio/1. Studio Shell and Workspace Layout Specification.md b/docs/specs/studio/1. Studio Shell and Workspace Layout Specification.md index dcfa325c..5de9ba5a 100644 --- a/docs/specs/studio/1. Studio Shell and Workspace Layout Specification.md +++ b/docs/specs/studio/1. Studio Shell and Workspace Layout Specification.md @@ -44,15 +44,10 @@ The left workspace selector remains fixed in the baseline Studio shell. The baseline workspace set includes: -- Code Editor; - Asset Management; - Debugger/Profiler; - Shipper, temporarily represented by the current `BuilderWorkspace`. -Workspace-local behavior for the first `Code Editor` wave is defined in: - -- `5. Code Editor Workspace Specification.md` - `BuilderWorkspace` is transitional and must not be treated as a long-term architectural reference for the final shipping surface. ## Workspace Architecture Model @@ -71,7 +66,7 @@ Baseline workspace architecture rules are: The shell must not encourage a workspace model where every interaction falls back to whole-workspace refresh. Detailed local workspace composition remains workspace-owned. -For example, `Code Editor`-local layout, navigator behavior, tab rules, passive placeholder surfaces, document access-mode behavior, and editor-local save surfaces are not shell-global rules and must be defined by the workspace-local editor specification. +For example, `Assets`-local navigator behavior, detail-pane composition, and mutation flows are not shell-global rules and must be defined by the workspace-local specifications that still exist. Project-session boundaries may still exist above a workspace when the state must remain alive while the project window stays open. diff --git a/docs/specs/studio/5. Code Editor Workspace Specification.md b/docs/specs/studio/5. Code Editor Workspace Specification.md deleted file mode 100644 index b498d34d..00000000 --- a/docs/specs/studio/5. Code Editor Workspace Specification.md +++ /dev/null @@ -1,377 +0,0 @@ -# Code Editor Workspace Specification - -## Status - -Active - -## Applies To - -- `prometeu-studio` -- the Studio `Code Editor` workspace -- the first controlled editor write wave for supported documents including frontend sources - -## Purpose - -Define the normative Studio contract for the first `Code Editor` workspace wave. - -This specification stabilizes: - -- the baseline visual composition of the workspace, -- the `Project Navigator` role and scope, -- the controlled editable file-opening model, -- the responsive tab baseline, -- the editor-owned composition surfaces that host save and semantic-read UX, -- the gutter-based active-structure indicator model for semantic editor scopes, -- the editor-local save surfaces, -- and the workspace boundary with the integrated frontend semantic-read phase. - -## Authority and Precedence - -This specification extends: - -- [`1. Studio Shell and Workspace Layout Specification.md`](1.%20Studio%20Shell%20and%20Workspace%20Layout%20Specification.md) -- [`2. Studio UI Foundations Specification.md`](2.%20Studio%20UI%20Foundations%20Specification.md) -- [`3. Studio Components Module Specification.md`](3.%20Studio%20Components%20Module%20Specification.md) -- [`6. Project Document VFS Specification.md`](6.%20Project%20Document%20VFS%20Specification.md) -- [`7. Integrated LSP Semantic Read Phase Specification.md`](7.%20Integrated%20LSP%20Semantic%20Read%20Phase%20Specification.md) - -If this document conflicts with the global Studio shell specifications, the shell specifications control shell-wide behavior and this document controls workspace-local editor behavior. - -## Normative Inputs - -The `Code Editor` workspace must assume: - -- the Studio shell already mounts `Code Editor` as a baseline workspace, -- the current wave allows editing for the supported document classes classified by `prometeu-vfs` as editable, including frontend-scoped supported documents, -- all project files remain visible in the editor workspace even when only some are frontend-relevant, -- `prometeu.json` plus the selected frontend may identify source roots worth tagging, -- the integrated frontend semantic-read phase may add diagnostics, symbols, outline-facing structure, definition, and highlight for frontend documents, -- the integrated frontend semantic-read phase may later add dedicated structural-anchor metadata for exact scope-indicator anchoring, -- frontend semantic presentation contract data comes from frontend-owned metadata published through `FrontendSpec`, -- and the current wave must not depend on semantic behavior to remain coherent. - -This workspace may consume Studio project metadata and Studio-owned workspace framework primitives, but it must not infer a semantic-provider contract beyond the explicit frontend-owned descriptor surfaced by the integrated semantic-read phase. -This workspace must consume project tree and document data through `prometeu-vfs` rather than through editor-owned direct filesystem readers. -This workspace must consume document access policy and save capability from `prometeu-vfs` rather than rederiving editability locally. - -## Workspace Model - -The `Code Editor` workspace is: - -- project-aware, -- file-oriented, -- controlled-editable in this wave, with supported documents following the canonical access mode provided by `prometeu-vfs`, -- and not a full semantic IDE surface yet. - -The workspace must help the user: - -- see the full project tree, -- identify frontend-relevant source roots visually, -- open supported files into editor tabs, -- save editable supported documents through editor-local commands, -- consume frontend semantic-read UX provided through the integrated LSP phase when that phase is active, -- understand the active file context, -- and understand that broader IDE automation remains outside this wave. - -The workspace must not pretend to offer: - -- merge behavior, -- completion, -- rename, code actions, or formatting, -- or editor-owned semantic inference that bypasses the integrated LSP phase. - -## Baseline Layout - -The baseline workspace layout is: - -- a left editor column, -- a central editor work area, -- a lower helper region, -- and a bottom status bar. - -The left editor column must be a vertical stack containing: - -- a functional `Project Navigator` at the top, -- and a reserved `Outline` region below it. - -The central editor work area must contain: - -- a top command bar containing at least `Save` and `Save All`, -- a tab strip at the top, -- and the editor body below it. - -The lower helper region is present in this wave only as a passive placeholder. - -## Component Ownership Rules - -The `Code Editor` workspace must be implemented as a composition root plus child controls/panels rather than one monolithic render surface. - -Rules: - -- the workspace root should coordinate layout, workspace-level session state, and structural synchronization; -- the workspace root should consume project-session-owned document services such as `prometeu-vfs` rather than owning their lifecycle locally; -- the `Project Navigator`, tab strip, editor body, reserved `Outline`, helper region, and status bar should exist as explicit local surfaces; -- passive placeholder surfaces must remain visually real without implying unsupported functionality; -- and the first wave should preserve a clean path for later extraction of reusable Studio controls when the surfaces become stable enough to justify that move. - -## Project Navigator Rules - -### Primary Navigation Unit - -- The primary navigation unit is the project file or directory. -- The navigator must cover the whole project rather than only frontend-tagged roots. -- Frontend tagging is supplementary context, not an inclusion filter. - -### Structural Snapshot - -- The navigator must consume a structural project-tree entity provided by `prometeu-vfs`. -- That structural tree must not replace the filesystem as the source of truth. -- Content snapshots are separate and are only required for files that are actually opened in the editor through `prometeu-vfs`. -- The navigator may request more targeted tree refresh operations than a full-tree reload when the `prometeu-vfs` contract provides them. - -### Visibility and Ordering - -- All project files and directories must be visible in the navigator. -- Hidden files must be included by default. -- Folders must sort before files. -- Items within those groups must sort alphabetically. - -### Frontend-Aware Tagging - -- `prometeu.json` plus the selected frontend may be used to tag relevant source roots or source directories. -- That tagging must not hide non-source project files. -- That tagging must not imply semantic/editor-language ownership by the navigator itself. -- Rendering those tags remains a Studio UI concern even when the source data comes from `prometeu-vfs`. - -### Refresh Model - -- The navigator must perform one initial refresh when the project opens. -- The navigator must expose a manual refresh action directly on the navigator surface and route that request through `prometeu-vfs`. -- Watcher-driven automatic refresh is explicitly deferred from this wave. - -### Unsupported Files - -- Unsupported or non-text files may still appear in the navigator. -- File support and unsupported-file classification belong to `prometeu-vfs`. -- Attempting to open such a file must show a simple modal stating that the file is not supported in this wave. -- The workspace must not fake a partial preview to imply unsupported file-format coverage. - -## Tabs and File Opening Rules - -- Selecting a supported file that is not already open must open it in a new tab. -- File opening must resolve document content through `prometeu-vfs`. -- The editor must maintain opened-file content in memory for the active Studio session only. -- Frontend-scoped supported documents may coexist in tabs with other editable supported documents. -- The tab strip must be responsive rather than fixed to one hardcoded tab count. -- Overflow tabs must remain accessible through an IntelliJ-style overflow control. -- The active tab must remain visible. -- The tab label must use only the file name with extension. - -The first wave must not define: - -- tab pinning, -- drag-and-drop tab reordering, -- grouped tabs, -- split editors. - -Project-session-owned cross-session tab restoration is accepted for the project-local Studio state wave. - -Rules: - -- persisted editor restoration state must come from the project-session-owned `.studio/` state store rather than from an editor-owned ad hoc file; -- accepted restoration scope in this wave is limited to open tabs and active tab; -- editor layout restoration accepted in this wave may include divider-driven editor sizing, `Project Navigator` expansion state, and dock-panel configuration such as `Outline` and `Helper` open/closed state plus their restored size; -- restoration must degrade safely when a previously open file is missing or unsupported. - -## Access-Mode and Save Model - -The first `Code Editor` write wave is controlled rather than universally editable. - -Rules: - -- the workspace must treat `prometeu-vfs` as the canonical source of document access mode for supported files; -- the workspace must not infer frontend scope from path heuristics, local UI state, or ad hoc extension checks; -- supported frontend-scoped documents may be editable when `prometeu-vfs` classifies them as editable; -- editable scope is limited to the supported textual classes exposed by `prometeu-vfs` for this wave, including supported frontend sources; -- the workspace must expose save behavior only through an editor-local command bar containing at least `Save` and `Save All`; -- the global shell `Save` menu item must not be the save surface for this wave; -- save intent must route through `prometeu-vfs`, which remains the owner of persistence policy; -- the active indentation policy for editable documents MUST come from project-local setup rather than from file-content heuristics; -- the status-bar indentation chip MUST display the active configured policy, not inferred file contents; -- pressing `Tab` in an editable document MUST insert spaces according to the active configured indentation width; -- the active indentation policy MUST remain stable while the user edits document contents; -- opening a file whose existing indentation diverges from the configured policy MUST NOT trigger automatic reformatting; -- and the workspace must not define local merge/conflict behavior against disk changes. - -## Outline Rules - -- The `Outline` region must exist structurally in this wave. -- Before the integrated LSP semantic-read phase is implemented, it may show a discreet placeholder state. -- When the integrated LSP semantic-read phase is active, the `Outline` region may render frontend document-symbol structure and workspace-symbol-backed navigation owned by that phase. -- The workspace must not fake semantic outline structure before real semantic ownership exists. - -## Helper Region Rules - -- The helper region must exist structurally in this wave. -- Before the integrated LSP semantic-read phase is implemented, it may remain passive. -- It exists only to stabilize workspace composition and reserve future space. -- It may later host diagnostics or related semantic-read detail for frontend documents without changing workspace ownership. -- It must not become a substitute for the shell-level `Activity` surface. - -## Integrated Semantic-Read Boundary - -- Frontend documents may be editable when `prometeu-vfs` grants editable access mode. -- Diagnostics, document symbols, workspace symbols, outline-facing structure, definition, and frontend highlight must come through the integrated LSP semantic-read phase rather than from editor-local inference. -- Exact anchor positions for semantic scope indicators must come from frontend-owned structural metadata rather than Studio-local text scanning when that metadata is available. -- Opened frontend documents must be analyzed from the VFS-owned in-memory snapshot exposed through `prometeu-vfs`. -- Unopened frontend documents may be analyzed from filesystem-backed state exposed through the same `prometeu-vfs` boundary. -- Non-frontend highlight may remain Studio-local in this phase. -- Frontend highlight must come from the integrated LSP semantic-read phase and use frontend-owned semantic presentation contract data derived from `FrontendSpec`. -- Frontend semantic presentation resources must remain frontend-owned and must not be replaced by a Studio-owned generic fallback theme. -- When semantic presentation descriptor data or usable frontend resources are absent, the workspace must continue without semantic highlight for that frontend document. -- The workspace must not surface this condition as a product-facing editor error. -- The workspace must not treat semantic-read over editorial snapshots as authorization for build participation or for bypassing `prometeu-vfs` access policy. - -## Inline Hint Rules - -Inline hints must be treated as a host-generic editor capability rather than as a PBS-only feature. - -The Studio `Code Editor` must render inline hints only from frontend-owned semantic payloads transported through the integrated semantic-read phase. - -The editor must not invent: - -- hint existence policy, -- hint text, -- hint categories, -- or host-owned semantic fallback hints. - -If a frontend publishes valid inline hints through the accepted semantic-read contract, the editor must render them. - -If a frontend does not publish inline hints for a construct, the editor must not synthesize one. - -Inline hints are decorative only. - -Therefore the editor must ensure that inline hints: - -- do not modify document text; -- do not become part of persisted file content; -- do not participate as copied document text; -- do not redefine selection ranges; -- and do not redefine caret movement over the text model. - -The completed capability must render inline hints as real inline editor decorations attached to document positions inside the editor flow. - -An approximate visual implementation may exist only as an explicit transitional wave. - -Any transitional approximation: - -- must be documented as transitional; -- must not redefine the final editor contract; -- and must converge to real inline rendering in a later execution step. - -When only some inline hint spans remain valid under degraded semantic analysis, the editor must continue rendering those valid spans rather than disabling all inline hints for the document. - -## Scope Indicator Rules - -The default semantic scope-indicator surface in the Code Editor must remain the gutter. - -The first active-state wave must render at most two simultaneous semantic indicators: - -- `activeContainer` -- `activeScope` - -The editor must not restore the previous full ancestry stack as the default active-state presentation. - -`activeScope` must be selected as the smallest structural range that contains the caret. - -`activeContainer` must be selected as the immediate structural ancestor of `activeScope`. - -If no valid structural ancestor exists, the editor may omit `activeContainer`. - -The editor must not promote a higher semantic owner such as function, type, or module when a nearer structural ancestor exists. - -The concrete visual presentation of `activeContainer` and `activeScope` remains frontend-owned. This specification intentionally does not fix: - -- colors, -- stroke style, -- dashed versus solid treatment, -- opacity, -- thickness, -- or equivalent visual-emphasis details. - -The Studio editor must only preserve the semantic distinction between the two indicator roles. - -Exact guide start and end anchoring must consume the dedicated structural-anchor semantic surface defined by the integrated semantic-read specification. - -The editor must not treat local brace scanning heuristics as the final production contract for exact anchor placement. - -## Status Bar Rules - -The status bar must remain mostly passive in this wave. - -Its left side must show the breadcrumb path of the active file, such as `proj > src > file.pbs`. - -Its right side must show: - -- `L:C`, -- line separator, -- tabs/spaces mode, -- file extension or language, -- and access-mode state. - -For this wave: - -- `L:C` may remain a visual placeholder, -- editable non-frontend documents may show their current file-type state without implying build participation, -- hard `read-only` frontend documents must show an explicit `read-only` state, -- and the status-bar `read-only` surface should be shaped so it can evolve into a per-file toggle later without requiring a model rewrite. - -## Session State Rules - -Visual/editorial state in this wave is session-local only. - -That includes at minimum: - -- open tabs, -- active tab selection, -- tree expansion state, -- and similar visual editor state. - -The following remain outside editor-owned session state: - -- project-session ownership of `prometeu-vfs`, -- structural project-tree data returned by `prometeu-vfs`, -- support classification rules, -- document loading responsibilities, -- save persistence policy, -- and build-facing document ownership. - -Editable documents may have session-local editorial snapshots while the project session remains open. -Those snapshots are editorial only and must not be treated as canonical build input by implication. - -Persisting that state across Studio executions is deferred. - -## Non-Goals - -- merge/conflict resolution -- watcher-driven automatic refresh -- public `prometeu-vfs` event APIs -- helper panel functionality -- editor-owned semantic analysis that bypasses the integrated LSP phase -- frontend editing -- completion, rename, code actions, or formatting -- a normative editor event contract in this wave -- any implication that editor-owned in-memory snapshots participate in the build -- host-owned semantic inline hint policy - -## Exit Criteria - -This specification is complete enough when: - -- the controlled write-wave scope is unambiguous, -- the `Project Navigator` and tab responsibilities are explicit, -- editor-local `Save` and `Save All` are part of the normative workspace contract, -- hard frontend `read-only` behavior is explicit in both warning and status-bar surfaces, -- the workspace boundary with the integrated frontend semantic-read phase is explicit, -- placeholder versus functional regions are clearly separated, -- and excluded frontend editing and completion behavior are clearly outside the current contract. diff --git a/docs/specs/studio/6. Project Document VFS Specification.md b/docs/specs/studio/6. Project Document VFS Specification.md deleted file mode 100644 index 3efd9559..00000000 --- a/docs/specs/studio/6. Project Document VFS Specification.md +++ /dev/null @@ -1,235 +0,0 @@ -# Project Document VFS Specification - -## Status - -Active - -## Applies To - -- `prometeu-vfs` -- `prometeu-studio` -- the Studio project-document boundary for the first controlled Code Editor write wave - -## Purpose - -Define the normative Studio contract for `prometeu-vfs` as the project-document boundary consumed by Studio workspaces. - -This specification stabilizes: - -- `prometeu-vfs` module role, -- project-session ownership, -- the filesystem-backed first-wave contract, -- structural tree and document access responsibilities, -- canonical frontend scope and access policy ownership, -- editorial snapshot and save ownership for editable supported documents including frontend sources, -- the semantic-read consumer boundary used by the integrated LSP phase, -- the RPC-first public API baseline, -- and explicit first-wave exclusions such as public event publication and watchers. - -## Authority and Precedence - -This specification extends: - -- [`1. Studio Shell and Workspace Layout Specification.md`](1.%20Studio%20Shell%20and%20Workspace%20Layout%20Specification.md) -- [`5. Code Editor Workspace Specification.md`](5.%20Code%20Editor%20Workspace%20Specification.md) - -If this document conflicts with shell-wide Studio rules, the shell specification controls shell-wide behavior and this document controls the project-document boundary contract. - -## Normative Inputs - -`prometeu-vfs` must assume: - -- the current migration wave carries only the Code Editor capabilities that already exist today, -- the initial backend is filesystem-backed, -- the boundary is project-scoped rather than product-global, -- the boundary must outlive workspace focus changes for an opened project, -- Studio UI remains the owner of visual tree state and error presentation, -- and the integrated `prometeu-lsp` phase consumes this boundary as a semantic-read client rather than as a persistence owner. - -`prometeu-vfs` must not infer: - -- watcher-driven refresh in this wave, -- public event API exposure in this wave, -- build participation for editorial snapshots by implication, -- or ownership over non-Studio domains such as packer assets. - -## Module Role - -`prometeu-vfs` is: - -- the Studio project-document boundary, -- the owner of project structural tree data for the covered scope, -- the owner of project document resolution for the covered scope, -- the owner of file support and unsupported-file classification for the covered scope, -- the owner of document access policy for the covered scope, -- the owner of save persistence for editable documents in this wave, -- and the required path through which Studio accesses project-document filesystem state in this wave. - -`prometeu-vfs` is not: - -- a visual tree control, -- a Studio shell replacement, -- a product-wide universal filesystem layer, -- or a public event transport in this wave. - -## Project Session Ownership - -The primary `prometeu-vfs` instance must belong to the Studio project session. - -Rules: - -- a project-scoped `prometeu-vfs` instance must be created when a Studio project session is opened; -- that instance must remain alive while the project session remains open; -- switching workspace focus must not destroy or recreate the project-document state by default; -- the `Code Editor` workspace must consume the session-owned `prometeu-vfs` instance rather than owning the boundary lifecycle itself; -- the project-session scope must cover only the opened project. - -## Filesystem Access Rules - -For the scope covered by this specification, Studio must access the project filesystem through `prometeu-vfs`. - -Rules: - -- the first implementation must be filesystem-backed; -- direct filesystem reads for project tree and document loading must not remain a workspace-owned responsibility in the Code Editor; -- this rule does not grant `prometeu-vfs` ownership over unrelated domains or unrelated filesystem responsibilities elsewhere in the product. - -## Structural Tree Contract - -`prometeu-vfs` must expose a structural representation of the project tree. - -Rules: - -- the structural tree must cover project content only; -- the structural tree must contain structural and documentary data only; -- the structural tree must not contain visual presentation state; -- the structural tree must not contain navigator chrome decisions; -- the structural tree may include structural metadata useful to Studio consumers; -- consumers may request narrower refreshes than a full-tree reload when the request remains within the project boundary. - -The following concerns remain outside `prometeu-vfs`: - -- visual expansion state, -- selection state, -- focus state, -- reveal or scroll behavior, -- icon choice, -- and other view-model concerns of the navigator UI. - -## Document Access Contract - -`prometeu-vfs` must own document resolution for the covered Studio scope. - -Rules: - -- opening a supported file in the Code Editor must go through `prometeu-vfs`; -- the returned document content must describe only project-session document state for the opened project; -- `prometeu-vfs` must classify each supported document as at least editable or hard `read-only`; -- unsupported documents must remain distinguishable from supported `read-only` and supported editable documents; -- `prometeu-vfs` must own editable in-memory editorial snapshots for the current Studio session; -- save operations for editable documents in this wave must persist those editorial snapshots to disk through `prometeu-vfs`; -- Studio consumers must treat `prometeu-vfs` access policy as canonical rather than rederiving editability locally; -- and editorial snapshots must remain outside build-facing document state. - -## Frontend Scope Contract - -Frontend scope must be decided canonically inside `prometeu-vfs`. - -Rules: - -- `FrontendSpec.allowedExtensions` is the source of truth for frontend scope in this wave; -- the VFS document contract must expose a canonical frontend-compatible `typeId` or equivalent scope marker derived from that source of truth; -- consumers must not infer frontend scope from raw dynamic language identifiers, path heuristics, or local UI extension checks; -- frontend-scoped supported documents must be editable in this wave when they are supported by the current frontend; -- the initial editable set is limited to the currently supported textual classes represented as `text`, `json`, `ndjson`, `bash`, and supported frontend source documents resolved from `FrontendSpec.allowedExtensions`; -- and no additional editable class may be inferred by implementation convenience during this wave. - -## Document Access Context - -`prometeu-vfs` must reserve a single access-context entity for document-access-related values. - -Rules: - -- the access-context entity may remain session-local in this wave; -- it must already support lookup and mutation under current demand; -- future persistence may be added later without redesigning the access model; -- and the current reservation must not be treated as authorization for build participation or broader product-wide state ownership. - -## Semantic-Read Consumer Boundary - -`prometeu-vfs` must remain the source-of-truth document substrate consumed by the integrated LSP semantic-read phase. - -Rules: - -- opened frontend documents must be exposed to `prometeu-lsp` from the in-memory editorial snapshot held by `prometeu-vfs`, including dirty snapshots not yet saved to disk; -- unopened frontend documents may be exposed to `prometeu-lsp` from filesystem-backed state through the same boundary; -- `prometeu-lsp` must not bypass `prometeu-vfs` with ad hoc filesystem reads inside Studio UI code; -- `prometeu-lsp` must not become the owner of save, persistence, or access policy; -- semantic analysis over editorial snapshots must remain separate from build-facing document ownership; -- and this boundary must remain suitable for frontend diagnostics, symbols, definition, and highlight without implying frontend edit rights. - -## Support and Plugin Rules - -Support and unsupported-file decisions belong to `prometeu-vfs`. - -Rules: - -- file support classification must be decided inside `prometeu-vfs`; -- plugin or handler resolution for supported file access must be decided inside `prometeu-vfs`; -- Studio UI may render the resulting success or failure state, but it must not own the classification rule itself. - -## Communication Model - -The official first-wave `prometeu-vfs` API is RPC-oriented. - -Rules: - -- commands and queries are the public API baseline for this wave; -- internal runtime events may exist inside `prometeu-vfs`; -- those events must remain internal in this wave; -- internal events must not be promoted to public API by inference during planning or implementation. - -## Refresh and Watchers - -Refresh remains manual in this wave. - -Rules: - -- Studio consumers may request manual refresh through `prometeu-vfs`; -- watcher-driven automatic refresh is deferred; -- file watching must not be introduced implicitly while implementing this specification. - -## Cross-Domain Boundary - -`prometeu-vfs` belongs to the Studio domain. - -Rules: - -- `prometeu-vfs` serves `prometeu-lsp` as a consumer-facing substrate for the semantic-read phase; -- `prometeu-lsp` remains a separate layer and must not be renamed into `prometeu-vfs`; -- `prometeu-vfs` must not absorb packer responsibilities; -- `prometeu-vfs` must not redefine asset ownership; -- extending this boundary outside project-document concerns requires a new decision. - -## Non-Goals - -- public event publication -- watcher-driven refresh -- dirty tracking -- merge or conflict handling -- non-project content snapshots -- a generic product-wide filesystem abstraction -- treating editorial snapshots as canonical build input - -## Exit Criteria - -This specification is complete enough when: - -- `prometeu-vfs` ownership is clearly separated from shell and workspace UI ownership, -- the project-session lifecycle rule is unambiguous, -- the structural tree contract is explicitly non-visual, -- frontend scope and access policy ownership are explicit, -- editable supported-document snapshot and save ownership are explicit, -- the semantic-read consumer boundary with `prometeu-lsp` is explicit, -- the RPC-first public API rule is explicit, -- and deferred public events and watchers are clearly out of scope. diff --git a/docs/specs/studio/7. Integrated LSP Semantic Read Phase Specification.md b/docs/specs/studio/7. Integrated LSP Semantic Read Phase Specification.md deleted file mode 100644 index 61ca1f1b..00000000 --- a/docs/specs/studio/7. Integrated LSP Semantic Read Phase Specification.md +++ /dev/null @@ -1,183 +0,0 @@ -# Integrated LSP Semantic Read Phase Specification - -## Status - -Active - -## Applies To - -- `prometeu-studio` -- `prometeu-vfs` -- `prometeu-lsp` -- the integrated frontend semantic phase in the Studio `Code Editor` workspace - -## Purpose - -Define the normative Studio contract for the integrated frontend semantic-read phase that arrives before any frontend editing release. - -This specification stabilizes: - -- the phase boundary between semantic ownership and frontend editing ownership, -- the ownership relationship between `prometeu-vfs`, `prometeu-lsp`, and the Studio editor, -- the minimum semantic capability set for frontend documents, -- the dedicated semantic surface used for structural anchors and guide-aware editor structure, -- the packaging expectations for the public `prometeu-lsp` API surface, -- and the explicit exclusions that remain outside this phase. - -## Authority and Precedence - -This specification extends: - -- [`5. Code Editor Workspace Specification.md`](5.%20Code%20Editor%20Workspace%20Specification.md) -- [`6. Project Document VFS Specification.md`](6.%20Project%20Document%20VFS%20Specification.md) - -If this document conflicts with shell-wide Studio rules, shell rules control shell behavior, the Code Editor specification controls workspace-local editor UX, the VFS specification controls document-boundary ownership, and this document controls the integrated semantic-read phase itself. - -## Normative Inputs - -The integrated semantic-read phase must assume: - -- frontend-scoped documents may be editable under the controlled write wave exposed by `prometeu-vfs`, -- editable supported documents remain governed by the controlled write wave, -- `FrontendSpec.allowedExtensions` remains the source of truth for frontend scope, -- `FrontendSpec` is the canonical source of frontend semantic presentation contract data, -- `prometeu-vfs` owns document state, snapshots, persistence, and access policy, -- and semantic-read over editorial snapshots must remain separate from build-facing ownership. - -## Phase Boundary - -This phase is a semantic phase for frontend documents, not an ownership phase for frontend editing. - -Rules: - -- no capability in this phase may override `prometeu-vfs` access policy, save policy, or snapshot ownership; -- completion, rename, code actions, and formatting remain outside this phase. - -## Ownership Rules - -- `prometeu-vfs` owns document state, access policy, editorial snapshots, and persistence. -- `prometeu-lsp` is a semantic consumer above `prometeu-vfs`. -- the Studio `Code Editor` owns UX surfaces that render semantic-read output. -- each frontend owns its semantic vocabulary and semantic presentation resources. -- build-facing document ownership remains outside this phase. - -`prometeu-lsp` must not become the owner of: - -- save, -- persistence, -- document access policy, -- frontend semantic presentation assets, -- or frontend edit-right release. - -## Document Source-of-Truth Rules - -- opened frontend documents must be analyzed from the in-memory snapshot exposed by `prometeu-vfs`; -- unopened frontend documents may be analyzed from filesystem-backed state exposed through the same `prometeu-vfs` boundary; -- Studio UI code must not bypass `prometeu-vfs` with ad hoc file loading for semantic-read behavior; -- semantic-read over editorial snapshots must not be treated as canonical build input by implication. - -## Minimum Capability Set - -The minimum semantic capability set of this phase must include: - -- diagnostics for frontend documents; -- document symbols for frontend documents; -- workspace symbols for frontend documents; -- outline-facing structural symbol data; -- go-to-definition for frontend documents; -- frontend semantic highlight. - -The phase may ship the dedicated structural-anchor surface after the baseline capability set is stable, but Studio and frontend implementations must treat that surface as the canonical source of exact scope-indicator anchoring once it exists. - -The phase may also ship a dedicated inline-hint semantic surface. - -Once shipped, frontend and Studio implementations must treat that surface as the canonical source of decorative inline hint payloads. - -## Highlight Ownership Rules - -- frontend highlight must come from semantic information provided through `prometeu-lsp`; -- frontend highlight must use frontend-owned semantic presentation contract data derived from `FrontendSpec`; -- `prometeu-lsp` must expose a dedicated semantic presentation descriptor derived from the resolved `FrontendSpec`; -- that descriptor must remain simple and include frontend-owned `semanticKeys` plus frontend-owned `resources` in the same message surface; -- `prometeu-lsp` must not collapse frontend semantic keys into host-owned generic categories; -- Studio must project semantic keys mechanically to CSS classes without semantic translation; -- frontend semantic presentation resources must remain under frontend `resources/` and be resolved like ordinary Java resources; -- when semantic presentation descriptor data or usable resources are absent, Studio must continue without semantic highlight; -- this condition must not become a product-facing Studio error and may at most produce normal development logs; -- non-frontend highlight may remain on the existing Studio-local highlighting path in this phase. - -## Inline Hint Ownership Rules - -- frontend inline hints must come from semantic information provided through `prometeu-lsp`; -- frontend hint existence and hint payload semantics remain frontend-owned; -- `prometeu-lsp` must expose a dedicated transport contract for inline hints rather than relying on Studio-local inference; -- `prometeu-lsp` must preserve deterministic anchor information required for host rendering; -- `prometeu-lsp` must not invent host-owned hint policy when a frontend does not publish hints; -- Studio must render transported hints mechanically as host decorations rather than as document text; -- valid inline hint spans must survive partial degradation when the frontend can still produce them; -- invalid or missing hint spans may be omitted locally; -- Studio must not disable all inline hints for a document solely because some hint spans are unavailable. - -## Structural Anchor Semantic Surface - -Exact structural anchoring for editor scope indicators must not be overloaded into `documentSymbols`. - -`documentSymbols` remains the outline and navigation surface. - -Guide-oriented structure must be exposed through a dedicated semantic surface for structural anchors and related guide metadata. - -That dedicated surface must be frontend-owned and language-agnostic. - -The contract must describe generic structural positions rather than PBS-specific brace semantics. - -The surface must be able to represent structures whose boundaries are expressed by: - -- braces; -- keywords; -- indentation-derived blocks; -- or mixed delimiter schemes. - -At minimum, the dedicated structural-anchor surface must be able to communicate: - -- structural ranges that can participate in active-scope selection; -- immediate parentage or equivalent information needed to recover the nearest ancestor relationship; -- exact structural anchor positions used for guide start and end placement; -- enough structural identity to distinguish the active structural range from its immediate container. - -The semantic-read contract must not require Studio to scan source text in order to discover the final structural anchor positions. - -Temporary local heuristics may exist only as development aids. They must not become the canonical production contract. - -The exact serialized schema of this dedicated surface may evolve in implementation plans, but any accepted schema must preserve the invariants above. - -## Packaging Rules - -The public `prometeu-lsp` API should follow flat packaging similar to `prometeu-packer-api`. - -Rules: - -- public contract surfaces should remain shallow and explicit; -- packages such as `dtos`, `messages`, and `events` are the preferred shape for public API grouping where those surfaces exist; -- deep public packaging by internal implementation concern should be avoided; -- runtime or implementation layering may exist internally, but it must not leak into the public contract surface by default. - -## Non-Goals - -- frontend save policy -- completion -- rename -- code actions -- formatting -- build participation inferred from editorial snapshots -- external-editor compatibility requirements -- Studio-owned semantic hint generation - -## Exit Criteria - -This specification is complete enough when: - -- the semantic-read versus frontend-editing phase boundary is explicit, -- `prometeu-vfs` and `prometeu-lsp` ownership remains unambiguous, -- the minimum semantic capability set is explicit, -- frontend and non-frontend highlight ownership is clearly separated, -- and the excluded editing and completion capabilities remain unambiguous. diff --git a/docs/specs/studio/8. Project-Local Studio State Specification.md b/docs/specs/studio/8. Project-Local Studio State Specification.md index 70b9a703..3f50d8ff 100644 --- a/docs/specs/studio/8. Project-Local Studio State Specification.md +++ b/docs/specs/studio/8. Project-Local Studio State Specification.md @@ -22,7 +22,6 @@ This specification implements the accepted decision for project-local Studio sta It extends: - [`1. Studio Shell and Workspace Layout Specification.md`](1.%20Studio%20Shell%20and%20Workspace%20Layout%20Specification.md) -- [`5. Code Editor Workspace Specification.md`](5.%20Code%20Editor%20Workspace%20Specification.md) ## Core Rules @@ -31,7 +30,7 @@ It extends: 3. The main session-restoration store MUST remain a single file at `.studio/state.json`. 4. The main session-restoration store MUST be versioned. 5. The main session-restoration store MUST load when the project session opens. -6. Restorable shell and editor state accepted by this wave MUST restore when the project shell mounts. +6. Restorable shell state accepted by this wave MUST restore when the project shell mounts. 7. The main session-restoration store MUST save when the project shell or project session closes. 8. Missing, invalid, or schema-incompatible session-restoration state MUST fall back to safe default values and MUST NOT block project open. 9. Project-local setup configuration MUST live in a separate file at `.studio/setup.json`. @@ -44,13 +43,11 @@ The main session-restoration store MUST include: - `shellLayout` - `openShellState` -- `editorRestoration` Wave-1 accepted meaning is: -- `shellLayout`: restorable layout state already accepted by implementation, including divider positions and equivalent layout proportions for accepted workspaces such as `Assets` and `Code Editor`, `Project Navigator` expansion state, and editor dock-panel open/closed plus restored-size configuration; +- `shellLayout`: restorable layout state already accepted by implementation, including divider positions and equivalent layout proportions for accepted workspaces such as `Assets`; - `openShellState`: which workspace or equivalent shell-owned project view was open; -- `editorRestoration`: open editor tabs and active tab. ## Project-Local Setup Configuration @@ -61,8 +58,8 @@ Rules: - project-local setup MUST live in `.studio/setup.json`; - project-local setup MUST be treated as project configuration rather than session state; - project-local setup MAY contain runtime-oriented values such as the Prometeu runtime path; -- project-local setup MUST own the project-wide editor indentation policy; -- the editor indentation policy MUST define at least indentation mode and indentation width; +- project-local setup MAY continue carrying project-wide indentation policy defaults for future code-tooling integrations; +- the indentation policy MUST define at least indentation mode and indentation width; - when setup does not provide an explicit indentation policy, consumers MUST resolve it to `spaces` with width `4`; - project-local setup MAY grow with additional manual or automatic configuration keys over time; - consumers such as `Play` MUST read project-local setup from the dedicated setup file rather than from `.studio/state.json`; diff --git a/docs/specs/studio/README.md b/docs/specs/studio/README.md index 67aa024e..affec2d3 100644 --- a/docs/specs/studio/README.md +++ b/docs/specs/studio/README.md @@ -54,10 +54,7 @@ The current Studio core corpus is: 2. [`2. Studio UI Foundations Specification.md`](2.%20Studio%20UI%20Foundations%20Specification.md) 3. [`3. Studio Components Module Specification.md`](3.%20Studio%20Components%20Module%20Specification.md) 4. [`4. Assets Workspace Specification.md`](4.%20Assets%20Workspace%20Specification.md) -5. [`5. Code Editor Workspace Specification.md`](5.%20Code%20Editor%20Workspace%20Specification.md) -6. [`6. Project Document VFS Specification.md`](6.%20Project%20Document%20VFS%20Specification.md) -7. [`7. Integrated LSP Semantic Read Phase Specification.md`](7.%20Integrated%20LSP%20Semantic%20Read%20Phase%20Specification.md) -8. [`8. Project-Local Studio State Specification.md`](8.%20Project-Local%20Studio%20State%20Specification.md) +5. [`8. Project-Local Studio State Specification.md`](8.%20Project-Local%20Studio%20State%20Specification.md) ## Reading Order @@ -67,19 +64,14 @@ Recommended order: 2. shared UI foundations; 3. components module policy; 4. assets workspace behavior; -5. project document VFS boundary; -6. code editor workspace behavior; -7. integrated LSP semantic-read behavior; -8. project-local Studio state behavior. +5. project-local Studio state behavior. ## Current Wave Notes -The current `Code Editor` wave is not globally read-only anymore. +The embedded Studio code-editor stack was removed by `DEC-0031`. Normative reminders: -- editable scope is limited to supported non-frontend textual documents classified by `prometeu-vfs`; -- frontend-scoped supported documents remain hard `read-only`; -- the editor-local `Save` and `Save All` surfaces belong to the `Code Editor` workspace rather than the shell; -- editorial in-memory snapshots remain outside build-facing state; -- frontend semantic-read capability lands before any frontend editing release and is documented by the integrated LSP phase specification. +- the active Studio workspace corpus is `Assets`, `Debug`, and `Shipper`; +- project-local Studio session state remains normative and is owned by `StudioProjectSession`; +- any future external-editor backend or replacement language-service architecture requires a new accepted decision before new Studio specs are introduced. diff --git a/prometeu-studio/src/main/java/p/studio/utilities/i18n/I18n.java b/prometeu-studio/src/main/java/p/studio/utilities/i18n/I18n.java index 6eb889dc..b423f17b 100644 --- a/prometeu-studio/src/main/java/p/studio/utilities/i18n/I18n.java +++ b/prometeu-studio/src/main/java/p/studio/utilities/i18n/I18n.java @@ -78,38 +78,6 @@ public enum I18n { TOOLBAR_STOP("toolbar.stop"), TOOLBAR_EXPORT("toolbar.export"), - WORKSPACE_CODE("workspace.code"), - CODE_EDITOR_NAVIGATOR_TITLE("codeEditor.navigator.title"), - CODE_EDITOR_NAVIGATOR_REFRESH("codeEditor.navigator.refresh"), - CODE_EDITOR_NAVIGATOR_REVEAL_ACTIVE("codeEditor.navigator.revealActive"), - CODE_EDITOR_NAVIGATOR_PLACEHOLDER("codeEditor.navigator.placeholder"), - CODE_EDITOR_NAVIGATOR_DETAIL("codeEditor.navigator.detail"), - CODE_EDITOR_OUTLINE_TITLE("codeEditor.outline.title"), - CODE_EDITOR_OUTLINE_PLACEHOLDER("codeEditor.outline.placeholder"), - CODE_EDITOR_OUTLINE_SYMBOLS("codeEditor.outline.symbols"), - CODE_EDITOR_OUTLINE_EMPTY_SYMBOLS("codeEditor.outline.emptySymbols"), - CODE_EDITOR_HELPER_TITLE("codeEditor.helper.title"), - CODE_EDITOR_HELPER_PLACEHOLDER("codeEditor.helper.placeholder"), - CODE_EDITOR_HELPER_DIAGNOSTICS("codeEditor.helper.diagnostics"), - CODE_EDITOR_HELPER_EMPTY_DIAGNOSTICS("codeEditor.helper.emptyDiagnostics"), - CODE_EDITOR_TABS_PLACEHOLDER("codeEditor.tabs.placeholder"), - CODE_EDITOR_TABS_OVERFLOW("codeEditor.tabs.overflow"), - CODE_EDITOR_STATUS_BREADCRUMB("codeEditor.status.breadcrumb"), - CODE_EDITOR_STATUS_POSITION("codeEditor.status.position"), - CODE_EDITOR_STATUS_LINE_SEPARATOR("codeEditor.status.lineSeparator"), - CODE_EDITOR_STATUS_INDENTATION("codeEditor.status.indentation"), - CODE_EDITOR_STATUS_LANGUAGE("codeEditor.status.language"), - CODE_EDITOR_COMMAND_SAVE("codeEditor.command.save"), - CODE_EDITOR_COMMAND_SAVE_ALL("codeEditor.command.saveAll"), - CODE_EDITOR_CLOSE_DIRTY_TITLE("codeEditor.closeDirty.title"), - CODE_EDITOR_CLOSE_DIRTY_MESSAGE("codeEditor.closeDirty.message"), - CODE_EDITOR_CLOSE_DIRTY_SAVE("codeEditor.closeDirty.save"), - CODE_EDITOR_CLOSE_DIRTY_DISCARD("codeEditor.closeDirty.discard"), - CODE_EDITOR_CLOSE_DIRTY_CANCEL("codeEditor.closeDirty.cancel"), - CODE_EDITOR_WARNING_FRONTEND_READ_ONLY("codeEditor.warning.frontendReadOnly"), - CODE_EDITOR_UNSUPPORTED_FILE_TITLE("codeEditor.unsupportedFile.title"), - CODE_EDITOR_UNSUPPORTED_FILE_MESSAGE("codeEditor.unsupportedFile.message"), - WORKSPACE_SHIPPER("workspace.shipper"), WORKSPACE_SHIPPER_LOGS("workspace.shipper.logs"), WORKSPACE_SHIPPER_BUTTON_RUN("workspace.shipper.button.run"), diff --git a/prometeu-studio/src/main/resources/i18n/messages.properties b/prometeu-studio/src/main/resources/i18n/messages.properties index d0bb1aa4..0df5cfe4 100644 --- a/prometeu-studio/src/main/resources/i18n/messages.properties +++ b/prometeu-studio/src/main/resources/i18n/messages.properties @@ -3,7 +3,7 @@ app.projectTitle=Prometeu Studio - {0} shield.loadingProject=Loading project {0}... shield.version=Version {0} shield.status.indexing=Indexing sources and restoring services... -shield.status.restoring=Restoring workspace surfaces and editor state... +shield.status.restoring=Restoring workspace surfaces and project state... shield.phase.indexing=Indexing shield.phase.preparing=Preparing UI shield.phase.restoring=Restoring State @@ -69,37 +69,6 @@ wizard.error.indentationRequired=Indentation width must be selected. toolbar.play=Play toolbar.stop=Stop toolbar.export=Export -workspace.code=Code -codeEditor.navigator.title=Project Navigator -codeEditor.navigator.refresh=Refresh -codeEditor.navigator.revealActive=Reveal active file -codeEditor.navigator.placeholder=Project navigation lands in the next implementation slice. -codeEditor.navigator.detail=This first shell reserves the full navigator surface, its refresh action, and the left-column composition without wiring project-tree data yet. -codeEditor.outline.title=Outline -codeEditor.outline.placeholder=Open a frontend document to inspect semantic symbols. -codeEditor.outline.symbols=Symbols -codeEditor.outline.emptySymbols=No semantic symbols are currently available for the active frontend document. -codeEditor.helper.title=Editor Helper -codeEditor.helper.placeholder=Open a frontend document to inspect semantic diagnostics. -codeEditor.helper.diagnostics=Diagnostics -codeEditor.helper.emptyDiagnostics=No diagnostics for the active frontend document. -codeEditor.tabs.placeholder=no-file-open.txt -codeEditor.tabs.overflow=More -codeEditor.status.breadcrumb=proj > src > file.pbs -codeEditor.status.position=L:C -codeEditor.status.lineSeparator=LF -codeEditor.status.indentation=Spaces: 4 -codeEditor.status.language=Text -codeEditor.command.save=Save -codeEditor.command.saveAll=Save All -codeEditor.closeDirty.title=Unsaved changes -codeEditor.closeDirty.message=Save changes to {0} before closing? -codeEditor.closeDirty.save=Save -codeEditor.closeDirty.discard=Discard -codeEditor.closeDirty.cancel=Cancel -codeEditor.warning.frontendReadOnly=This frontend file is read-only in this wave. It cannot be edited or saved yet. -codeEditor.unsupportedFile.title=Unsupported file -codeEditor.unsupportedFile.message=This file is not supported in this wave: {0} workspace.shipper=Shipper workspace.shipper.logs=Logs workspace.shipper.button.run=Build diff --git a/prometeu-studio/src/main/resources/i18n/messages_pt_BR.properties b/prometeu-studio/src/main/resources/i18n/messages_pt_BR.properties index 71ec4f02..5e00b3ed 100644 --- a/prometeu-studio/src/main/resources/i18n/messages_pt_BR.properties +++ b/prometeu-studio/src/main/resources/i18n/messages_pt_BR.properties @@ -12,7 +12,6 @@ toolbar.play=Executar toolbar.stop=Parar toolbar.export=Exportar -workspace.code=Cdigo workspace.shipper=Empacotador workspace.shipper.logs=Logs workspace.shipper.button.run=Construir diff --git a/prometeu-studio/src/main/resources/themes/default-prometeu.css b/prometeu-studio/src/main/resources/themes/default-prometeu.css index 3e5910ab..c98780ff 100644 --- a/prometeu-studio/src/main/resources/themes/default-prometeu.css +++ b/prometeu-studio/src/main/resources/themes/default-prometeu.css @@ -352,24 +352,6 @@ -fx-background-color: #17191d; } -.editor-workspace { - -fx-background-color: #15181d; -} - -.editor-workspace-layout { - -fx-padding: 16; - -fx-background-color: #15181d; -} - -.editor-workspace-split { - -fx-background-color: transparent; -} - -.editor-workspace-split > .split-pane-divider { - -fx-background-color: transparent; - -fx-padding: 0 8 0 8; -} - .workspace-dock-split { -fx-background-color: transparent; } @@ -386,544 +368,6 @@ -fx-padding: 0; } -.editor-workspace-left-column, -.editor-workspace-center-column { - -fx-spacing: 12; -} - -.editor-workspace-panel { - -fx-background-color: #1b1f25; - -fx-background-radius: 12; - -fx-border-radius: 12; - -fx-border-color: #2a313c; -} - -.editor-workspace-panel-header { - -fx-alignment: center-left; -} - -.editor-workspace-header-icon-button { - -fx-background-color: transparent; - -fx-border-color: transparent; - -fx-background-radius: 4; - -fx-border-radius: 4; - -fx-padding: 6; -} - -.editor-workspace-header-icon-button:hover { - -fx-background-color: #243243; - -fx-border-color: #556f8b; -} - -.editor-workspace-panel-content { - -fx-padding: 6 0 0 0; -} - -.editor-workspace-panel-title { - -fx-text-fill: #eff5fb; - -fx-font-size: 14px; - -fx-font-weight: bold; -} - -.editor-workspace-placeholder { - -fx-text-fill: #c3cfdb; - -fx-font-size: 12px; -} - -.editor-workspace-placeholder-detail { - -fx-text-fill: #8896a7; - -fx-font-size: 11px; -} - -.editor-workspace-navigator-panel { - -fx-min-height: 320px; -} - -.editor-workspace-tree { - -fx-background-color: transparent; - -fx-border-color: transparent; -} - -.editor-workspace-tree .tree-cell { - -fx-background-color: transparent; - -fx-text-fill: #d6e0ea; - -fx-font-size: 14px; - -fx-padding: 4 6 4 4; -} - -.editor-workspace-tree .tree-cell:selected { - -fx-background-color: #24415e; - -fx-text-fill: #ffffff; -} - -.editor-workspace-tree .tree-disclosure-node { - -fx-padding: 0 4 0 0; -} - -.editor-workspace-tree .tree-disclosure-node .arrow { - -fx-background-color: #8ea4ba; -} - -.editor-workspace-tree .tree-cell:selected .tree-disclosure-node .arrow { - -fx-background-color: #e8f3ff; -} - -.editor-workspace-tree-cell-tagged { - -fx-font-weight: bold; -} - -.editor-workspace-tree-cell-root { - -fx-font-weight: bold; - -fx-text-fill: #f4f8fc; -} - -.editor-workspace-icon { - -fx-min-width: 14; - -fx-min-height: 14; - -fx-pref-width: 14; - -fx-pref-height: 14; - -fx-max-width: 14; - -fx-max-height: 14; - -fx-alignment: center; -} - -.editor-workspace-icon-shape { - -fx-scale-x: 0.88; - -fx-scale-y: 0.88; -} - -.editor-workspace-icon-folder-default { - -fx-fill: #8792a1; -} - -.editor-workspace-icon-folder-source { - -fx-fill: #4ea0ef; -} - -.editor-workspace-icon-folder-build { - -fx-fill: #d88a3d; -} - -.editor-workspace-icon-file { - -fx-fill: #b0bac6; -} - -.editor-workspace-icon-cog { - -fx-fill: #c6d0da; -} - -.editor-workspace-icon-refresh { - -fx-fill: #eff5fb; -} - -.editor-workspace-icon-target { - -fx-fill: #eff5fb; -} - -.editor-workspace-icon-lock-closed { - -fx-fill: #f6d78f; -} - -.editor-workspace-icon-lock-open { - -fx-fill: #bde7c7; -} - -.editor-workspace-outline-panel { - -fx-min-height: 0; -} - -.editor-workspace-outline-scroll { - -fx-background-color: transparent; - -fx-background-insets: 0; -} - -.editor-workspace-outline-scroll > .viewport { - -fx-background-color: transparent; -} - -.editor-workspace-outline-summary { - -fx-text-fill: #dce6f0; -} - -.editor-workspace-outline-section-title { - -fx-font-size: 11px; - -fx-font-weight: 700; - -fx-text-fill: #8fb1d2; - -fx-padding: 4 0 0 0; -} - -.editor-workspace-outline-list { - -fx-spacing: 6; -} - -.editor-workspace-outline-item { - -fx-text-fill: #d7e2ec; - -fx-font-size: 12px; -} - -.editor-workspace-outline-diagnostic-error { - -fx-text-fill: #ff9a9a; -} - -.editor-workspace-outline-diagnostic-warning { - -fx-text-fill: #f6d78f; -} - -.editor-workspace-tab-strip { - -fx-padding: 8 12 8 12; - -fx-background-color: #1b1f25; - -fx-background-radius: 0; - -fx-border-radius: 0; - -fx-border-color: #2a313c; -} - -.editor-workspace-code-area { - -fx-background-color: #171c22; - -fx-font-size: 15px; - -fx-highlight-fill: #26405c; - -fx-highlight-text-fill: #eef4fb; -} - -.editor-workspace-tab-button { - -fx-background-radius: 0; - -fx-border-radius: 0; - -fx-padding: 0 8 0 12; - -fx-alignment: center-left; - -fx-font-size: 12px; - -fx-background-color: #20262f; - -fx-border-color: #343f4d; - -fx-border-width: 1; - -fx-text-fill: #d6dde6; -} - -.editor-workspace-tab-content { - -fx-spacing: 8; - -fx-alignment: center-left; -} - -.editor-workspace-tab-label { - -fx-alignment: center-left; - -fx-font-size: 12px; -} - -.editor-workspace-tab-dirty-indicator { - -fx-background-color: #d9e3ef; - -fx-background-radius: 999; - -fx-border-radius: 999; - -fx-opacity: 0.9; -} - -.editor-workspace-tab-close-chip { - -fx-alignment: center; - -fx-background-color: #131820; - -fx-background-radius: 999; - -fx-border-color: #485667; - -fx-border-radius: 999; - -fx-border-width: 1; - -fx-padding: 0; - -fx-cursor: hand; -} - -.editor-workspace-tab-close-icon { - -fx-fill: transparent; - -fx-stroke: #cfd8e2; - -fx-stroke-width: 1.1; -} - -.editor-workspace-tab-button-active { - -fx-background-color: #16283d; - -fx-border-color: #8fc4f2 #516579 #516579 #516579; - -fx-border-width: 3 1 1 1; - -fx-text-fill: #ffffff; - -fx-font-weight: bold; -} - -.editor-workspace-tab-button-read-only { - -fx-background-color: #252b34; - -fx-border-color: #47515d; - -fx-text-fill: #d9dee5; -} - -.editor-workspace-tab-button-read-only .editor-workspace-tab-label { - -fx-text-fill: #d9dee5; -} - -.editor-workspace-tab-button-read-only .editor-workspace-tab-dirty-indicator { - -fx-background-color: #d9dee5; -} - -.editor-workspace-tab-button-read-only .editor-workspace-tab-close-icon { - -fx-stroke: #d9dee5; -} - -.editor-workspace-tab-button-read-only .editor-workspace-tab-close-chip { - -fx-background-color: #171c23; - -fx-border-color: #4f5b68; -} - -.editor-workspace-tab-button-read-only:hover { - -fx-background-color: #2b323d; - -fx-border-color: #5b6878; - -fx-text-fill: #eff4fa; -} - -.editor-workspace-tab-button-read-only:hover .editor-workspace-tab-label { - -fx-text-fill: #eff4fa; -} - -.editor-workspace-tab-button-read-only:hover .editor-workspace-tab-dirty-indicator { - -fx-background-color: #eff4fa; -} - -.editor-workspace-tab-button-read-only:hover .editor-workspace-tab-close-chip { - -fx-background-color: #1c232c; - -fx-border-color: #6b7989; -} - -.editor-workspace-tab-button-read-only:hover .editor-workspace-tab-close-chip:hover { - -fx-background-color: #2a3440; - -fx-border-color: #90a2b5; -} - -.editor-workspace-tab-button-read-only:hover .editor-workspace-tab-close-chip:hover .editor-workspace-tab-close-icon { - -fx-stroke: #f7fbff; -} - -.editor-workspace-tab-button-read-only:hover .editor-workspace-tab-close-chip:pressed { - -fx-background-color: #364351; - -fx-border-color: #a8bbce; -} - -.editor-workspace-tab-button-read-only.editor-workspace-tab-button-active { - -fx-background-color: #16283d; - -fx-border-color: #8fc4f2 #516579 #516579 #516579; - -fx-border-width: 3 1 1 1; - -fx-text-fill: #ffffff; - -fx-font-weight: bold; -} - -.editor-workspace-tab-button-read-only.editor-workspace-tab-button-active:hover { - -fx-background-color: #1c3148; - -fx-border-color: #a7d7ff #5c738b #5c738b #5c738b; -} - -.editor-workspace-tab-button-editable { - -fx-background-color: #203226; - -fx-border-color: #4d6f58; - -fx-text-fill: #e8f6eb; -} - -.editor-workspace-tab-button-editable .editor-workspace-tab-label { - -fx-text-fill: #e8f6eb; -} - -.editor-workspace-tab-button-editable .editor-workspace-tab-dirty-indicator { - -fx-background-color: #b9f0c7; -} - -.editor-workspace-tab-button-editable .editor-workspace-tab-close-icon { - -fx-stroke: #e8f6eb; -} - -.editor-workspace-tab-button-editable .editor-workspace-tab-close-chip { - -fx-background-color: #15211a; - -fx-border-color: #557363; -} - -.editor-workspace-tab-button-editable:hover { - -fx-background-color: #29412f; - -fx-border-color: #6f957a; - -fx-text-fill: #f4fff5; -} - -.editor-workspace-tab-button-editable:hover .editor-workspace-tab-label { - -fx-text-fill: #f4fff5; -} - -.editor-workspace-tab-button-editable:hover .editor-workspace-tab-dirty-indicator { - -fx-background-color: #f4fff5; -} - -.editor-workspace-tab-button-editable:hover .editor-workspace-tab-close-chip { - -fx-background-color: #192720; - -fx-border-color: #789886; -} - -.editor-workspace-tab-button-editable:hover .editor-workspace-tab-close-chip:hover { - -fx-background-color: #27382d; - -fx-border-color: #9fc0ac; -} - -.editor-workspace-tab-button-editable:hover .editor-workspace-tab-close-chip:hover .editor-workspace-tab-close-icon { - -fx-stroke: #ffffff; -} - -.editor-workspace-tab-button-editable:hover .editor-workspace-tab-close-chip:pressed { - -fx-background-color: #314739; - -fx-border-color: #b2d2bf; -} - -.editor-workspace-tab-button-editable.editor-workspace-tab-button-active { - -fx-background-color: #1d3a2a; - -fx-border-color: #8ad3a2 #587464 #587464 #587464; - -fx-border-width: 3 1 1 1; - -fx-text-fill: #ffffff; - -fx-font-weight: bold; -} - -.editor-workspace-tab-button-active .editor-workspace-tab-label { - -fx-text-fill: #ffffff; - -fx-font-weight: bold; -} - -.editor-workspace-tab-button-active .editor-workspace-tab-dirty-indicator { - -fx-background-color: #ffffff; -} - -.editor-workspace-tab-button-active .editor-workspace-tab-close-icon { - -fx-stroke: #ffffff; -} - -.editor-workspace-tab-button-active .editor-workspace-tab-close-chip { - -fx-background-color: rgba(255, 255, 255, 0.08); - -fx-border-color: rgba(255, 255, 255, 0.22); -} - -.editor-workspace-tab-button-active:hover .editor-workspace-tab-close-chip:hover { - -fx-background-color: rgba(255, 255, 255, 0.18); - -fx-border-color: rgba(255, 255, 255, 0.42); -} - -.editor-workspace-tab-button-active:hover .editor-workspace-tab-close-chip:pressed { - -fx-background-color: rgba(255, 255, 255, 0.28); - -fx-border-color: rgba(255, 255, 255, 0.56); -} - -.editor-workspace-tab-button-editable.editor-workspace-tab-button-active:hover { - -fx-background-color: #234532; - -fx-border-color: #a5efbd #688676 #688676 #688676; -} - - -.editor-workspace-tab-overflow { - -fx-background-radius: 0; - -fx-border-radius: 0; - -fx-padding: 0 12 0 12; - -fx-min-width: 128; - -fx-pref-width: 128; - -fx-max-width: 128; - -fx-min-height: 34; - -fx-pref-height: 34; - -fx-max-height: 34; -} - -.editor-workspace-tab-overflow-item { - -fx-text-fill: #d9e2eb; - -fx-font-size: 12px; - -fx-padding: 0 10 0 10; - -fx-background-color: transparent; -} - -.editor-workspace-code-area .content { - -fx-background-color: #171c22; -} - -.editor-workspace-code-area .paragraph-box { - -fx-background-color: #171c22; -} - -.editor-workspace-code-area .lineno { - -fx-background-color: #12161c; - -fx-text-fill: #6f7a86; - -fx-padding: 0 12 0 12; - -fx-font-family: "JetBrains Mono Medium", "JetBrains Mono", "Iosevka", "Cascadia Mono", "IBM Plex Mono", monospace; - -fx-font-size: 14px; -} - -.editor-workspace-code-area .text { - -fx-fill: #f2f6fb; - -fx-font-family: "JetBrains Mono Medium", "JetBrains Mono", "Iosevka", "Cascadia Mono", "IBM Plex Mono", monospace; - -fx-font-size: 14px; -} - -.editor-workspace-code-area .caret { - -fx-stroke: #ffd27a; -} - -.editor-workspace-editor-surface { - -fx-background-color: #171c22; - -fx-border-color: #2a313c; - -fx-border-width: 1; -} - -.editor-workspace-editor-viewport { - -fx-background-color: transparent; -} - -.editor-workspace-code-area .text.editor-inline-hint { - -fx-fill: #707070; - -rtfx-background-color: #1f242f; - -fx-font-family: "JetBrains Mono Medium", "JetBrains Mono", "Iosevka", "Cascadia Mono", "IBM Plex Mono", monospace; - -fx-font-size: 13px; -} - -.editor-workspace-code-area .text.editor-inline-hint-type { - -fx-fill: #707070; - -rtfx-background-color: #1f242f; -} - -.editor-workspace-code-area-type-text .text { - -fx-fill: #eef3f8; -} - -.editor-workspace-command-bar { - -fx-padding: 10 12 0 12; - -fx-alignment: center-left; -} - -.editor-workspace-command-button { - -fx-alignment: center; - -fx-pref-width: 118px; - -fx-min-width: 118px; -} - -.editor-workspace-warning { - -fx-alignment: center-left; - -fx-spacing: 8; - -fx-padding: 8 12 8 12; - -fx-background-color: #3b2a10; - -fx-border-color: #8f6730; - -fx-border-width: 0 0 1 0; - -fx-text-fill: #f7ddb0; - -fx-font-size: 12px; -} - -.editor-workspace-warning-counter { - -fx-text-fill: #f3d8a7; - -fx-font-size: 11px; - -fx-font-weight: 700; -} - -.editor-workspace-warning-button { - -fx-min-width: 24; - -fx-pref-width: 24; - -fx-max-width: 24; - -fx-min-height: 24; - -fx-pref-height: 24; - -fx-max-height: 24; - -fx-padding: 0; - -fx-background-color: #4b3413; - -fx-border-color: #9a7440; - -fx-text-fill: #f7ddb0; - -fx-font-size: 11px; - -fx-background-radius: 4; - -fx-border-radius: 4; -} - -.editor-workspace-warning-button:hover { - -fx-background-color: #5a4018; - -fx-border-color: #b38749; -} .workspace-dock-pane { -fx-collapsible: true; @@ -960,13 +404,6 @@ -fx-border-insets: 0; } -.editor-workspace-helper-panel { - -fx-min-height: 0; -} - -.editor-workspace-helper-summary { - -fx-text-fill: #dce6f0; -} .workspace-dock-pane-collapsed { -fx-background-insets: 0; @@ -984,107 +421,6 @@ -fx-border-insets: 0; } -.editor-workspace-status-bar { - -fx-padding: 6 12 6 12; - -fx-background-color: #1b1f25; - -fx-background-radius: 12; - -fx-border-radius: 12; - -fx-border-color: #2a313c; - -fx-min-height: 40; - -fx-pref-height: 40; - -fx-max-height: 40; -} - -.editor-workspace-status-breadcrumb { - -fx-alignment: center-left; -} - -.editor-workspace-status-breadcrumb-segment { - -fx-alignment: center-left; - -fx-padding: 0 2 0 0; -} - -.editor-workspace-status-breadcrumb-segment-root { - -fx-font-weight: bold; -} - -.editor-workspace-status-breadcrumb-text { - -fx-text-fill: #d4dde7; - -fx-font-size: 12px; -} - -.editor-workspace-status-breadcrumb-segment-root .editor-workspace-status-breadcrumb-text { - -fx-text-fill: #f1f7fd; - -fx-font-weight: bold; -} - -.editor-workspace-status-breadcrumb-separator { - -fx-text-fill: #6f7e8e; - -fx-font-size: 12px; -} - -.editor-workspace-status-chip { - -fx-background-color: #11151b; - -fx-background-radius: 4; - -fx-border-radius: 4; - -fx-border-color: #2a313c; - -fx-padding: 0 8 0 8; - -fx-text-fill: #c5d2de; - -fx-font-size: 11px; - -fx-alignment: center; - -fx-min-height: 28; - -fx-pref-height: 28; - -fx-max-height: 28; -} - -.editor-workspace-status-chip-type-text { - -fx-background-color: #11151b; - -fx-border-color: #2a313c; - -fx-text-fill: #c5d2de; -} - -.editor-workspace-status-chip-position { - -fx-min-width: 44; - -fx-pref-width: 44; - -fx-max-width: 44; -} - -.editor-workspace-status-chip-line-separator { - -fx-min-width: 44; - -fx-pref-width: 44; - -fx-max-width: 44; -} - -.editor-workspace-status-chip-indentation { - -fx-min-width: 84; - -fx-pref-width: 84; - -fx-max-width: 84; -} - -.editor-workspace-status-chip-language { - -fx-min-width: 72; - -fx-pref-width: 72; - -fx-max-width: 72; -} - -.editor-workspace-status-chip-access-mode { - -fx-min-width: 36; - -fx-pref-width: 36; - -fx-max-width: 36; - -fx-padding: 0; -} - -.editor-workspace-status-chip-read-only { - -fx-background-color: #3b2a10; - -fx-border-color: #8f6730; - -fx-text-fill: #f7ddb0; -} - -.editor-workspace-status-chip-editable { - -fx-background-color: #203226; - -fx-border-color: #5a8567; - -fx-text-fill: #ebfff0; -} .assets-workspace-split { -fx-background-color: transparent; diff --git a/prometeu-studio/src/main/resources/themes/editor/presentations/bash.css b/prometeu-studio/src/main/resources/themes/editor/presentations/bash.css deleted file mode 100644 index a3e2c6a9..00000000 --- a/prometeu-studio/src/main/resources/themes/editor/presentations/bash.css +++ /dev/null @@ -1,39 +0,0 @@ -.editor-workspace-code-area-type-bash .text { - -fx-fill: #edf2f7; -} - -.editor-workspace-code-area-type-bash .lineno { - -fx-text-fill: #788595; -} - -.editor-workspace-code-area-type-bash .text.editor-syntax-bash-shebang { - -fx-fill: #f0ae63; -} - -.editor-workspace-code-area-type-bash .text.editor-syntax-bash-comment { - -fx-fill: #7d8a98; -} - -.editor-workspace-code-area-type-bash .text.editor-syntax-bash-string { - -fx-fill: #dcbf88; -} - -.editor-workspace-code-area-type-bash .text.editor-syntax-bash-variable { - -fx-fill: #8fd4ff; -} - -.editor-workspace-code-area-type-bash .text.editor-syntax-bash-keyword { - -fx-fill: #d7a6ff; -} - -.editor-workspace-code-area-type-bash .text.editor-syntax-bash-builtin { - -fx-fill: #9fe2a0; -} - -.editor-workspace-code-area-type-bash .text.editor-syntax-bash-command { - -fx-fill: #7fc1ff; -} - -.editor-workspace-code-area-type-bash .text.editor-syntax-bash-operator { - -fx-fill: #c7d3de; -} diff --git a/prometeu-studio/src/main/resources/themes/editor/presentations/json.css b/prometeu-studio/src/main/resources/themes/editor/presentations/json.css deleted file mode 100644 index fa180ac1..00000000 --- a/prometeu-studio/src/main/resources/themes/editor/presentations/json.css +++ /dev/null @@ -1,41 +0,0 @@ -.editor-workspace-code-area-type-json { - -fx-highlight-fill: #204766; -} - -.editor-workspace-code-area-type-json .text { - -fx-fill: #dff3ff; -} - -.editor-workspace-code-area-type-json .lineno { - -fx-text-fill: #7e92a6; -} - -.editor-workspace-code-area-type-json .text.editor-syntax-json-key { - -fx-fill: #8fd4ff; -} - -.editor-workspace-code-area-type-json .text.editor-syntax-json-string { - -fx-fill: #d9c48f; -} - -.editor-workspace-code-area-type-json .text.editor-syntax-json-number { - -fx-fill: #9ee39f; -} - -.editor-workspace-code-area-type-json .text.editor-syntax-json-boolean { - -fx-fill: #f3a6d6; -} - -.editor-workspace-code-area-type-json .text.editor-syntax-json-null { - -fx-fill: #c89cff; -} - -.editor-workspace-code-area-type-json .text.editor-syntax-json-punctuation { - -fx-fill: #c8d5e2; -} - -.editor-workspace-status-chip-type-json { - -fx-background-color: #132433; - -fx-border-color: #4e88b8; - -fx-text-fill: #e2f4ff; -} -- 2.47.2 From 52211ea02c17a6e96625c6e712550dd93818f53b Mon Sep 17 00:00:00 2001 From: bQUARKz Date: Tue, 5 May 2026 13:39:24 +0100 Subject: [PATCH 04/37] add bare bones for a lsp --- .../prometeu-lsp-api/build.gradle.kts | 3 + prometeu-lsp/prometeu-lsp-v1/build.gradle.kts | 9 + .../p/studio/lsp/PrometeuStudioLspMain.java | 271 ++++++ settings.gradle.kts | 4 + .../main/assets/.prometeu/cache.json | 786 +++++++++--------- tools/vscode-extension/.gitignore | 35 + tools/vscode-extension/.vscode/launch.json | 17 + tools/vscode-extension/.vscode/tasks.json | 12 + tools/vscode-extension/package-lock.json | 139 ++++ tools/vscode-extension/package.json | 69 ++ tools/vscode-extension/src/extension.ts | 159 ++++ tools/vscode-extension/tsconfig.json | 20 + 12 files changed, 1131 insertions(+), 393 deletions(-) create mode 100644 prometeu-lsp/prometeu-lsp-api/build.gradle.kts create mode 100644 prometeu-lsp/prometeu-lsp-v1/build.gradle.kts create mode 100644 prometeu-lsp/prometeu-lsp-v1/src/main/java/p/studio/lsp/PrometeuStudioLspMain.java create mode 100644 tools/vscode-extension/.gitignore create mode 100644 tools/vscode-extension/.vscode/launch.json create mode 100644 tools/vscode-extension/.vscode/tasks.json create mode 100644 tools/vscode-extension/package-lock.json create mode 100644 tools/vscode-extension/package.json create mode 100644 tools/vscode-extension/src/extension.ts create mode 100644 tools/vscode-extension/tsconfig.json diff --git a/prometeu-lsp/prometeu-lsp-api/build.gradle.kts b/prometeu-lsp/prometeu-lsp-api/build.gradle.kts new file mode 100644 index 00000000..5c470d4e --- /dev/null +++ b/prometeu-lsp/prometeu-lsp-api/build.gradle.kts @@ -0,0 +1,3 @@ +plugins { + id("gradle.java-library-conventions") +} \ No newline at end of file diff --git a/prometeu-lsp/prometeu-lsp-v1/build.gradle.kts b/prometeu-lsp/prometeu-lsp-v1/build.gradle.kts new file mode 100644 index 00000000..70154dda --- /dev/null +++ b/prometeu-lsp/prometeu-lsp-v1/build.gradle.kts @@ -0,0 +1,9 @@ +plugins { + id("gradle.java-library-conventions") +} + +dependencies { + implementation(project(":prometeu-infra")) + + implementation("org.eclipse.lsp4j:org.eclipse.lsp4j:1.0.0") +} \ No newline at end of file diff --git a/prometeu-lsp/prometeu-lsp-v1/src/main/java/p/studio/lsp/PrometeuStudioLspMain.java b/prometeu-lsp/prometeu-lsp-v1/src/main/java/p/studio/lsp/PrometeuStudioLspMain.java new file mode 100644 index 00000000..5fc34565 --- /dev/null +++ b/prometeu-lsp/prometeu-lsp-v1/src/main/java/p/studio/lsp/PrometeuStudioLspMain.java @@ -0,0 +1,271 @@ +package p.studio.lsp; + +import org.eclipse.lsp4j.*; +import org.eclipse.lsp4j.jsonrpc.Launcher; +import org.eclipse.lsp4j.launch.LSPLauncher; +import org.eclipse.lsp4j.services.*; + +import java.io.InputStream; +import java.io.OutputStream; +import java.net.InetAddress; +import java.net.ServerSocket; +import java.net.Socket; +import java.util.List; +import java.util.concurrent.CompletableFuture; + +public final class PrometeuStudioLspMain { + + private static final String HOST = "127.0.0.1"; + private static final int PORT = 7777; + + public static void main(String[] args) throws Exception { + InetAddress bindAddress = InetAddress.getByName(HOST); + + try (ServerSocket serverSocket = new ServerSocket(PORT, 50, bindAddress)) { + System.out.println("Prometeu Studio LSP listening on " + HOST + ":" + PORT); + + while (true) { + Socket socket = serverSocket.accept(); + + Thread clientThread = new Thread(() -> handleClient(socket)); + clientThread.setName("prometeu-lsp-client"); + clientThread.setDaemon(true); + clientThread.start(); + } + } + } + + private static void handleClient(Socket socket) { + try { + System.out.println("VS Code connected: " + socket.getRemoteSocketAddress()); + + InputStream input = socket.getInputStream(); + OutputStream output = socket.getOutputStream(); + + PrometeuLanguageServer server = new PrometeuLanguageServer(); + + Launcher launcher = + LSPLauncher.createServerLauncher(server, input, output); + + LanguageClient client = launcher.getRemoteProxy(); + server.connect(client); + + launcher.startListening(); + + } catch (Exception e) { + System.err.println("LSP client failed: " + e.getMessage()); + e.printStackTrace(); + } + } + + private static final class PrometeuLanguageServer implements LanguageServer, LanguageClientAware { + + private LanguageClient client; + private final TextDocumentService textDocumentService = new PrometeuTextDocumentService(this); + private final WorkspaceService workspaceService = new PrometeuWorkspaceService(); + + private boolean shutdownRequested = false; + + @Override + public void connect(LanguageClient client) { + this.client = client; + + if (textDocumentService instanceof PrometeuTextDocumentService service) { + service.connect(client); + } + } + + public LanguageClient client() { + return client; + } + + @Override + public CompletableFuture initialize(InitializeParams params) { + ServerCapabilities capabilities = new ServerCapabilities(); + + TextDocumentSyncOptions syncOptions = new TextDocumentSyncOptions(); + syncOptions.setOpenClose(true); + syncOptions.setChange(TextDocumentSyncKind.Full); + + SaveOptions saveOptions = new SaveOptions(); + saveOptions.setIncludeText(true); + syncOptions.setSave(saveOptions); + + capabilities.setTextDocumentSync(syncOptions); + capabilities.setHoverProvider(true); + + InitializeResult result = new InitializeResult(capabilities); + + ServerInfo serverInfo = new ServerInfo(); + serverInfo.setName("Prometeu Studio LSP"); + serverInfo.setVersion("0.1.0"); + result.setServerInfo(serverInfo); + + return CompletableFuture.completedFuture(result); + } + + @Override + public void initialized(InitializedParams params) { + if (client != null) { + client.logMessage(new MessageParams( + MessageType.Info, + "Hello from Prometeu Studio LSP" + )); + } + } + + @Override + public CompletableFuture shutdown() { + shutdownRequested = true; + return CompletableFuture.completedFuture(null); + } + + @Override + public void exit() { + System.out.println("LSP client requested exit. shutdownRequested=" + shutdownRequested); + + // Importantíssimo: + // Como isso está dentro do Studio, NÃO use System.exit(). + } + + @Override + public TextDocumentService getTextDocumentService() { + return textDocumentService; + } + + @Override + public WorkspaceService getWorkspaceService() { + return workspaceService; + } + } + + private static final class PrometeuTextDocumentService implements TextDocumentService { + + private final PrometeuLanguageServer server; + private LanguageClient client; + + private PrometeuTextDocumentService(PrometeuLanguageServer server) { + this.server = server; + } + + private void connect(LanguageClient client) { + this.client = client; + } + + @Override + public void didOpen(DidOpenTextDocumentParams params) { + String uri = params.getTextDocument().getUri(); + String text = params.getTextDocument().getText(); + + System.out.println("didOpen: " + uri); + + publishHelloDiagnostic(uri, text); + } + + @Override + public void didChange(DidChangeTextDocumentParams params) { + String uri = params.getTextDocument().getUri(); + + String text = ""; + if (!params.getContentChanges().isEmpty()) { + text = params.getContentChanges().get(0).getText(); + } + + System.out.println("didChange: " + uri); + + publishHelloDiagnostic(uri, text); + } + + @Override + public void didClose(DidCloseTextDocumentParams params) { + String uri = params.getTextDocument().getUri(); + + System.out.println("didClose: " + uri); + + if (client != null) { + client.publishDiagnostics(new PublishDiagnosticsParams(uri, List.of())); + } + } + + @Override + public void didSave(DidSaveTextDocumentParams params) { + String uri = params.getTextDocument().getUri(); + + System.out.println("didSave: " + uri); + + if (client != null) { + client.logMessage(new MessageParams( + MessageType.Info, + "Prometeu Studio saw save: " + uri + )); + } + } + + @Override + public CompletableFuture hover(HoverParams params) { + MarkupContent content = new MarkupContent(); + content.setKind(MarkupKind.MARKDOWN); + content.setValue(""" + **Prometeu Studio LSP** + + Hello from Java + LSP4J. + + This hover came from the Studio process. + """); + + Hover hover = new Hover(); + hover.setContents(content); + + return CompletableFuture.completedFuture(hover); + } + + private void publishHelloDiagnostic(String uri, String text) { + if (client == null) { + return; + } + + Diagnostic diagnostic = new Diagnostic(); + + diagnostic.setRange(new Range( + new Position(0, 0), + new Position(0, Math.max(1, firstLineLength(text))) + )); + + diagnostic.setSeverity(DiagnosticSeverity.Information); + diagnostic.setSource("Prometeu Studio"); + diagnostic.setMessage("Hello from Prometeu Studio LSP"); + + client.publishDiagnostics(new PublishDiagnosticsParams( + uri, + List.of(diagnostic) + )); + } + + private int firstLineLength(String text) { + if (text == null || text.isEmpty()) { + return 1; + } + + int newline = text.indexOf('\n'); + + if (newline < 0) { + return text.length(); + } + + return newline; + } + } + + private static final class PrometeuWorkspaceService implements WorkspaceService { + + @Override + public void didChangeConfiguration(DidChangeConfigurationParams params) { + System.out.println("didChangeConfiguration"); + } + + @Override + public void didChangeWatchedFiles(DidChangeWatchedFilesParams params) { + System.out.println("didChangeWatchedFiles: " + params.getChanges().size() + " changes"); + } + } +} \ No newline at end of file diff --git a/settings.gradle.kts b/settings.gradle.kts index dc36dbbc..a3801c38 100644 --- a/settings.gradle.kts +++ b/settings.gradle.kts @@ -5,9 +5,13 @@ plugins { rootProject.name = "prometeu-studio" include("prometeu-infra") + include("prometeu-packer:prometeu-packer-api") include("prometeu-packer:prometeu-packer-v1") +include("prometeu-lsp:prometeu-lsp-api") +include("prometeu-lsp:prometeu-lsp-v1") + include("prometeu-compiler:frontends:prometeu-frontend-pbs") include("prometeu-compiler:prometeu-compiler-core") include("prometeu-compiler:prometeu-build-pipeline") diff --git a/test-projects/main/assets/.prometeu/cache.json b/test-projects/main/assets/.prometeu/cache.json index ef4e0d61..7d30e3eb 100644 --- a/test-projects/main/assets/.prometeu/cache.json +++ b/test-projects/main/assets/.prometeu/cache.json @@ -24,14 +24,14 @@ "last_modified" : 1774359772403, "fingerprint" : "eeb7cc665386299403b7be1c272375d5077f3647c587f8033aa8c9275f840562", "metadata" : { + "palette" : { + "originalArgb8888" : [ -265674 ], + "convertedRgb565" : [ -122 ] + }, "tile" : { "width" : 32, "height" : 32, "paletteIndices" : "AQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAAAAAAAAAAABAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEAAAAAAAAAAAEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQAAAAAAAAAAAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAAAAAAAAAAABAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEAAAAAAAAAAAEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQAAAAAAAAAAAQEBAQEBAQEBAQEBAAAAAAAAAAAAAAAAAAAAAAAAAAABAQEBAQEBAQEBAQEAAAAAAAAAAAAAAAAAAAAAAAAAAAEBAQEBAQEBAQEBAQAAAAAAAAAAAAAAAAAAAAAAAAAAAQEBAQEBAQEBAQEBAAAAAAAAAAAAAAAAAAAAAAAAAAABAQEBAQEBAQEBAQEAAAAAAAAAAAAAAAAAAAAAAAAAAAEBAQEBAQEBAQEBAQAAAAAAAAAAAAAAAAAAAAAAAAAAAQEBAQEBAQEBAQEBAAAAAAAAAAAAAAAAAAAAAAAAAAABAQEBAQEBAQEBAQEAAAAAAAAAAAAAAAAAAAAAAAAAAAEBAQEBAQEBAQEBAQAAAAAAAAAAAAAAAAAAAQEBAQEBAQEBAQEBAQEBAQEBAAAAAAAAAAAAAAAAAAABAQEBAQEBAQEBAQEBAQEBAQEAAAAAAAAAAAAAAAAAAAEBAQEBAQEBAQEBAQEBAQEBAQAAAAAAAAAAAAAAAAAAAQEBAQEBAQEBAQEBAAAAAAAAAAAAAAAAAAAAAAAAAAABAQEBAQEBAQEBAQEAAAAAAAAAAAAAAAAAAAAAAAAAAAEBAQEBAQEBAQEBAQAAAAAAAAAAAAAAAAAAAQEBAQEBAQEBAQEBAQEBAQEBAAAAAAAAAAAAAAAAAAABAQEBAQEBAQEBAQEBAQEBAQEAAAAAAAAAAAAAAAAAAAEBAQEBAQEBAQEBAQEBAQEBAQAAAAAAAAAAAAAAAAAAAQEBAQEBAQEBAQEBAQEBAQEBAAAAAAAAAAAAAAAAAAABAQEBAQEBAQEBAQEBAQEBAQEAAAAAAAAAAAAAAAAAAAEBAQEBAQEBAQEBAQ==" - }, - "palette" : { - "originalArgb8888" : [ -265674 ], - "convertedRgb565" : [ -122 ] } }, "diagnostics" : [ ] @@ -42,14 +42,14 @@ "last_modified" : 1774359772405, "fingerprint" : "eeb7cc665386299403b7be1c272375d5077f3647c587f8033aa8c9275f840562", "metadata" : { + "palette" : { + "originalArgb8888" : [ -265674 ], + "convertedRgb565" : [ -122 ] + }, "tile" : { "width" : 32, "height" : 32, "paletteIndices" : "AQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAAAAAAAAAAABAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEAAAAAAAAAAAEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQAAAAAAAAAAAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAAAAAAAAAAABAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEAAAAAAAAAAAEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQAAAAAAAAAAAQEBAQEBAQEBAQEBAAAAAAAAAAAAAAAAAAAAAAAAAAABAQEBAQEBAQEBAQEAAAAAAAAAAAAAAAAAAAAAAAAAAAEBAQEBAQEBAQEBAQAAAAAAAAAAAAAAAAAAAAAAAAAAAQEBAQEBAQEBAQEBAAAAAAAAAAAAAAAAAAAAAAAAAAABAQEBAQEBAQEBAQEAAAAAAAAAAAAAAAAAAAAAAAAAAAEBAQEBAQEBAQEBAQAAAAAAAAAAAAAAAAAAAAAAAAAAAQEBAQEBAQEBAQEBAAAAAAAAAAAAAAAAAAAAAAAAAAABAQEBAQEBAQEBAQEAAAAAAAAAAAAAAAAAAAAAAAAAAAEBAQEBAQEBAQEBAQAAAAAAAAAAAAAAAAAAAQEBAQEBAQEBAQEBAQEBAQEBAAAAAAAAAAAAAAAAAAABAQEBAQEBAQEBAQEBAQEBAQEAAAAAAAAAAAAAAAAAAAEBAQEBAQEBAQEBAQEBAQEBAQAAAAAAAAAAAAAAAAAAAQEBAQEBAQEBAQEBAAAAAAAAAAAAAAAAAAAAAAAAAAABAQEBAQEBAQEBAQEAAAAAAAAAAAAAAAAAAAAAAAAAAAEBAQEBAQEBAQEBAQAAAAAAAAAAAAAAAAAAAQEBAQEBAQEBAQEBAQEBAQEBAAAAAAAAAAAAAAAAAAABAQEBAQEBAQEBAQEBAQEBAQEAAAAAAAAAAAAAAAAAAAEBAQEBAQEBAQEBAQEBAQEBAQAAAAAAAAAAAAAAAAAAAQEBAQEBAQEBAQEBAQEBAQEBAAAAAAAAAAAAAAAAAAABAQEBAQEBAQEBAQEBAQEBAQEAAAAAAAAAAAAAAAAAAAEBAQEBAQEBAQEBAQ==" - }, - "palette" : { - "originalArgb8888" : [ -265674 ], - "convertedRgb565" : [ -122 ] } }, "diagnostics" : [ ] @@ -60,14 +60,14 @@ "last_modified" : 1774359772406, "fingerprint" : "eeb7cc665386299403b7be1c272375d5077f3647c587f8033aa8c9275f840562", "metadata" : { + "palette" : { + "originalArgb8888" : [ -265674 ], + "convertedRgb565" : [ -122 ] + }, "tile" : { "width" : 32, "height" : 32, "paletteIndices" : "AQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAAAAAAAAAAABAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEAAAAAAAAAAAEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQAAAAAAAAAAAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAAAAAAAAAAABAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEAAAAAAAAAAAEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQAAAAAAAAAAAQEBAQEBAQEBAQEBAAAAAAAAAAAAAAAAAAAAAAAAAAABAQEBAQEBAQEBAQEAAAAAAAAAAAAAAAAAAAAAAAAAAAEBAQEBAQEBAQEBAQAAAAAAAAAAAAAAAAAAAAAAAAAAAQEBAQEBAQEBAQEBAAAAAAAAAAAAAAAAAAAAAAAAAAABAQEBAQEBAQEBAQEAAAAAAAAAAAAAAAAAAAAAAAAAAAEBAQEBAQEBAQEBAQAAAAAAAAAAAAAAAAAAAAAAAAAAAQEBAQEBAQEBAQEBAAAAAAAAAAAAAAAAAAAAAAAAAAABAQEBAQEBAQEBAQEAAAAAAAAAAAAAAAAAAAAAAAAAAAEBAQEBAQEBAQEBAQAAAAAAAAAAAAAAAAAAAQEBAQEBAQEBAQEBAQEBAQEBAAAAAAAAAAAAAAAAAAABAQEBAQEBAQEBAQEBAQEBAQEAAAAAAAAAAAAAAAAAAAEBAQEBAQEBAQEBAQEBAQEBAQAAAAAAAAAAAAAAAAAAAQEBAQEBAQEBAQEBAAAAAAAAAAAAAAAAAAAAAAAAAAABAQEBAQEBAQEBAQEAAAAAAAAAAAAAAAAAAAAAAAAAAAEBAQEBAQEBAQEBAQAAAAAAAAAAAAAAAAAAAQEBAQEBAQEBAQEBAQEBAQEBAAAAAAAAAAAAAAAAAAABAQEBAQEBAQEBAQEBAQEBAQEAAAAAAAAAAAAAAAAAAAEBAQEBAQEBAQEBAQEBAQEBAQAAAAAAAAAAAAAAAAAAAQEBAQEBAQEBAQEBAQEBAQEBAAAAAAAAAAAAAAAAAAABAQEBAQEBAQEBAQEBAQEBAQEAAAAAAAAAAAAAAAAAAAEBAQEBAQEBAQEBAQ==" - }, - "palette" : { - "originalArgb8888" : [ -265674 ], - "convertedRgb565" : [ -122 ] } }, "diagnostics" : [ ] @@ -78,14 +78,14 @@ "last_modified" : 1774359772408, "fingerprint" : "eeb7cc665386299403b7be1c272375d5077f3647c587f8033aa8c9275f840562", "metadata" : { + "palette" : { + "originalArgb8888" : [ -265674 ], + "convertedRgb565" : [ -122 ] + }, "tile" : { "width" : 32, "height" : 32, "paletteIndices" : "AQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAAAAAAAAAAABAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEAAAAAAAAAAAEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQAAAAAAAAAAAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAAAAAAAAAAABAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEAAAAAAAAAAAEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQAAAAAAAAAAAQEBAQEBAQEBAQEBAAAAAAAAAAAAAAAAAAAAAAAAAAABAQEBAQEBAQEBAQEAAAAAAAAAAAAAAAAAAAAAAAAAAAEBAQEBAQEBAQEBAQAAAAAAAAAAAAAAAAAAAAAAAAAAAQEBAQEBAQEBAQEBAAAAAAAAAAAAAAAAAAAAAAAAAAABAQEBAQEBAQEBAQEAAAAAAAAAAAAAAAAAAAAAAAAAAAEBAQEBAQEBAQEBAQAAAAAAAAAAAAAAAAAAAAAAAAAAAQEBAQEBAQEBAQEBAAAAAAAAAAAAAAAAAAAAAAAAAAABAQEBAQEBAQEBAQEAAAAAAAAAAAAAAAAAAAAAAAAAAAEBAQEBAQEBAQEBAQAAAAAAAAAAAAAAAAAAAQEBAQEBAQEBAQEBAQEBAQEBAAAAAAAAAAAAAAAAAAABAQEBAQEBAQEBAQEBAQEBAQEAAAAAAAAAAAAAAAAAAAEBAQEBAQEBAQEBAQEBAQEBAQAAAAAAAAAAAAAAAAAAAQEBAQEBAQEBAQEBAAAAAAAAAAAAAAAAAAAAAAAAAAABAQEBAQEBAQEBAQEAAAAAAAAAAAAAAAAAAAAAAAAAAAEBAQEBAQEBAQEBAQAAAAAAAAAAAAAAAAAAAQEBAQEBAQEBAQEBAQEBAQEBAAAAAAAAAAAAAAAAAAABAQEBAQEBAQEBAQEBAQEBAQEAAAAAAAAAAAAAAAAAAAEBAQEBAQEBAQEBAQEBAQEBAQAAAAAAAAAAAAAAAAAAAQEBAQEBAQEBAQEBAQEBAQEBAAAAAAAAAAAAAAAAAAABAQEBAQEBAQEBAQEBAQEBAQEAAAAAAAAAAAAAAAAAAAEBAQEBAQEBAQEBAQ==" - }, - "palette" : { - "originalArgb8888" : [ -265674 ], - "convertedRgb565" : [ -122 ] } }, "diagnostics" : [ ] @@ -96,14 +96,14 @@ "last_modified" : 1774359772409, "fingerprint" : "eeb7cc665386299403b7be1c272375d5077f3647c587f8033aa8c9275f840562", "metadata" : { + "palette" : { + "originalArgb8888" : [ -265674 ], + "convertedRgb565" : [ -122 ] + }, "tile" : { "width" : 32, "height" : 32, "paletteIndices" : "AQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAAAAAAAAAAABAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEAAAAAAAAAAAEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQAAAAAAAAAAAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAAAAAAAAAAABAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEAAAAAAAAAAAEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQAAAAAAAAAAAQEBAQEBAQEBAQEBAAAAAAAAAAAAAAAAAAAAAAAAAAABAQEBAQEBAQEBAQEAAAAAAAAAAAAAAAAAAAAAAAAAAAEBAQEBAQEBAQEBAQAAAAAAAAAAAAAAAAAAAAAAAAAAAQEBAQEBAQEBAQEBAAAAAAAAAAAAAAAAAAAAAAAAAAABAQEBAQEBAQEBAQEAAAAAAAAAAAAAAAAAAAAAAAAAAAEBAQEBAQEBAQEBAQAAAAAAAAAAAAAAAAAAAAAAAAAAAQEBAQEBAQEBAQEBAAAAAAAAAAAAAAAAAAAAAAAAAAABAQEBAQEBAQEBAQEAAAAAAAAAAAAAAAAAAAAAAAAAAAEBAQEBAQEBAQEBAQAAAAAAAAAAAAAAAAAAAQEBAQEBAQEBAQEBAQEBAQEBAAAAAAAAAAAAAAAAAAABAQEBAQEBAQEBAQEBAQEBAQEAAAAAAAAAAAAAAAAAAAEBAQEBAQEBAQEBAQEBAQEBAQAAAAAAAAAAAAAAAAAAAQEBAQEBAQEBAQEBAAAAAAAAAAAAAAAAAAAAAAAAAAABAQEBAQEBAQEBAQEAAAAAAAAAAAAAAAAAAAAAAAAAAAEBAQEBAQEBAQEBAQAAAAAAAAAAAAAAAAAAAQEBAQEBAQEBAQEBAQEBAQEBAAAAAAAAAAAAAAAAAAABAQEBAQEBAQEBAQEBAQEBAQEAAAAAAAAAAAAAAAAAAAEBAQEBAQEBAQEBAQEBAQEBAQAAAAAAAAAAAAAAAAAAAQEBAQEBAQEBAQEBAQEBAQEBAAAAAAAAAAAAAAAAAAABAQEBAQEBAQEBAQEBAQEBAQEAAAAAAAAAAAAAAAAAAAEBAQEBAQEBAQEBAQ==" - }, - "palette" : { - "originalArgb8888" : [ -265674 ], - "convertedRgb565" : [ -122 ] } }, "diagnostics" : [ ] @@ -114,14 +114,14 @@ "last_modified" : 1774359772411, "fingerprint" : "eeb7cc665386299403b7be1c272375d5077f3647c587f8033aa8c9275f840562", "metadata" : { + "palette" : { + "originalArgb8888" : [ -265674 ], + "convertedRgb565" : [ -122 ] + }, "tile" : { "width" : 32, "height" : 32, "paletteIndices" : "AQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAAAAAAAAAAABAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEAAAAAAAAAAAEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQAAAAAAAAAAAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAAAAAAAAAAABAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEAAAAAAAAAAAEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQAAAAAAAAAAAQEBAQEBAQEBAQEBAAAAAAAAAAAAAAAAAAAAAAAAAAABAQEBAQEBAQEBAQEAAAAAAAAAAAAAAAAAAAAAAAAAAAEBAQEBAQEBAQEBAQAAAAAAAAAAAAAAAAAAAAAAAAAAAQEBAQEBAQEBAQEBAAAAAAAAAAAAAAAAAAAAAAAAAAABAQEBAQEBAQEBAQEAAAAAAAAAAAAAAAAAAAAAAAAAAAEBAQEBAQEBAQEBAQAAAAAAAAAAAAAAAAAAAAAAAAAAAQEBAQEBAQEBAQEBAAAAAAAAAAAAAAAAAAAAAAAAAAABAQEBAQEBAQEBAQEAAAAAAAAAAAAAAAAAAAAAAAAAAAEBAQEBAQEBAQEBAQAAAAAAAAAAAAAAAAAAAQEBAQEBAQEBAQEBAQEBAQEBAAAAAAAAAAAAAAAAAAABAQEBAQEBAQEBAQEBAQEBAQEAAAAAAAAAAAAAAAAAAAEBAQEBAQEBAQEBAQEBAQEBAQAAAAAAAAAAAAAAAAAAAQEBAQEBAQEBAQEBAAAAAAAAAAAAAAAAAAAAAAAAAAABAQEBAQEBAQEBAQEAAAAAAAAAAAAAAAAAAAAAAAAAAAEBAQEBAQEBAQEBAQAAAAAAAAAAAAAAAAAAAQEBAQEBAQEBAQEBAQEBAQEBAAAAAAAAAAAAAAAAAAABAQEBAQEBAQEBAQEBAQEBAQEAAAAAAAAAAAAAAAAAAAEBAQEBAQEBAQEBAQEBAQEBAQAAAAAAAAAAAAAAAAAAAQEBAQEBAQEBAQEBAQEBAQEBAAAAAAAAAAAAAAAAAAABAQEBAQEBAQEBAQEBAQEBAQEAAAAAAAAAAAAAAAAAAAEBAQEBAQEBAQEBAQ==" - }, - "palette" : { - "originalArgb8888" : [ -265674 ], - "convertedRgb565" : [ -122 ] } }, "diagnostics" : [ ] @@ -132,14 +132,14 @@ "last_modified" : 1774359772412, "fingerprint" : "eeb7cc665386299403b7be1c272375d5077f3647c587f8033aa8c9275f840562", "metadata" : { + "palette" : { + "originalArgb8888" : [ -265674 ], + "convertedRgb565" : [ -122 ] + }, "tile" : { "width" : 32, "height" : 32, "paletteIndices" : "AQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAAAAAAAAAAABAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEAAAAAAAAAAAEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQAAAAAAAAAAAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAAAAAAAAAAABAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEAAAAAAAAAAAEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQAAAAAAAAAAAQEBAQEBAQEBAQEBAAAAAAAAAAAAAAAAAAAAAAAAAAABAQEBAQEBAQEBAQEAAAAAAAAAAAAAAAAAAAAAAAAAAAEBAQEBAQEBAQEBAQAAAAAAAAAAAAAAAAAAAAAAAAAAAQEBAQEBAQEBAQEBAAAAAAAAAAAAAAAAAAAAAAAAAAABAQEBAQEBAQEBAQEAAAAAAAAAAAAAAAAAAAAAAAAAAAEBAQEBAQEBAQEBAQAAAAAAAAAAAAAAAAAAAAAAAAAAAQEBAQEBAQEBAQEBAAAAAAAAAAAAAAAAAAAAAAAAAAABAQEBAQEBAQEBAQEAAAAAAAAAAAAAAAAAAAAAAAAAAAEBAQEBAQEBAQEBAQAAAAAAAAAAAAAAAAAAAQEBAQEBAQEBAQEBAQEBAQEBAAAAAAAAAAAAAAAAAAABAQEBAQEBAQEBAQEBAQEBAQEAAAAAAAAAAAAAAAAAAAEBAQEBAQEBAQEBAQEBAQEBAQAAAAAAAAAAAAAAAAAAAQEBAQEBAQEBAQEBAAAAAAAAAAAAAAAAAAAAAAAAAAABAQEBAQEBAQEBAQEAAAAAAAAAAAAAAAAAAAAAAAAAAAEBAQEBAQEBAQEBAQAAAAAAAAAAAAAAAAAAAQEBAQEBAQEBAQEBAQEBAQEBAAAAAAAAAAAAAAAAAAABAQEBAQEBAQEBAQEBAQEBAQEAAAAAAAAAAAAAAAAAAAEBAQEBAQEBAQEBAQEBAQEBAQAAAAAAAAAAAAAAAAAAAQEBAQEBAQEBAQEBAQEBAQEBAAAAAAAAAAAAAAAAAAABAQEBAQEBAQEBAQEBAQEBAQEAAAAAAAAAAAAAAAAAAAEBAQEBAQEBAQEBAQ==" - }, - "palette" : { - "originalArgb8888" : [ -265674 ], - "convertedRgb565" : [ -122 ] } }, "diagnostics" : [ ] @@ -150,14 +150,14 @@ "last_modified" : 1774359772413, "fingerprint" : "eeb7cc665386299403b7be1c272375d5077f3647c587f8033aa8c9275f840562", "metadata" : { + "palette" : { + "originalArgb8888" : [ -265674 ], + "convertedRgb565" : [ -122 ] + }, "tile" : { "width" : 32, "height" : 32, "paletteIndices" : "AQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAAAAAAAAAAABAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEAAAAAAAAAAAEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQAAAAAAAAAAAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAAAAAAAAAAABAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEAAAAAAAAAAAEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQAAAAAAAAAAAQEBAQEBAQEBAQEBAAAAAAAAAAAAAAAAAAAAAAAAAAABAQEBAQEBAQEBAQEAAAAAAAAAAAAAAAAAAAAAAAAAAAEBAQEBAQEBAQEBAQAAAAAAAAAAAAAAAAAAAAAAAAAAAQEBAQEBAQEBAQEBAAAAAAAAAAAAAAAAAAAAAAAAAAABAQEBAQEBAQEBAQEAAAAAAAAAAAAAAAAAAAAAAAAAAAEBAQEBAQEBAQEBAQAAAAAAAAAAAAAAAAAAAAAAAAAAAQEBAQEBAQEBAQEBAAAAAAAAAAAAAAAAAAAAAAAAAAABAQEBAQEBAQEBAQEAAAAAAAAAAAAAAAAAAAAAAAAAAAEBAQEBAQEBAQEBAQAAAAAAAAAAAAAAAAAAAQEBAQEBAQEBAQEBAQEBAQEBAAAAAAAAAAAAAAAAAAABAQEBAQEBAQEBAQEBAQEBAQEAAAAAAAAAAAAAAAAAAAEBAQEBAQEBAQEBAQEBAQEBAQAAAAAAAAAAAAAAAAAAAQEBAQEBAQEBAQEBAAAAAAAAAAAAAAAAAAAAAAAAAAABAQEBAQEBAQEBAQEAAAAAAAAAAAAAAAAAAAAAAAAAAAEBAQEBAQEBAQEBAQAAAAAAAAAAAAAAAAAAAQEBAQEBAQEBAQEBAQEBAQEBAAAAAAAAAAAAAAAAAAABAQEBAQEBAQEBAQEBAQEBAQEAAAAAAAAAAAAAAAAAAAEBAQEBAQEBAQEBAQEBAQEBAQAAAAAAAAAAAAAAAAAAAQEBAQEBAQEBAQEBAQEBAQEBAAAAAAAAAAAAAAAAAAABAQEBAQEBAQEBAQEBAQEBAQEAAAAAAAAAAAAAAAAAAAEBAQEBAQEBAQEBAQ==" - }, - "palette" : { - "originalArgb8888" : [ -265674 ], - "convertedRgb565" : [ -122 ] } }, "diagnostics" : [ ] @@ -168,14 +168,14 @@ "last_modified" : 1774359772415, "fingerprint" : "eeb7cc665386299403b7be1c272375d5077f3647c587f8033aa8c9275f840562", "metadata" : { + "palette" : { + "originalArgb8888" : [ -265674 ], + "convertedRgb565" : [ -122 ] + }, "tile" : { "width" : 32, "height" : 32, "paletteIndices" : "AQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAAAAAAAAAAABAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEAAAAAAAAAAAEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQAAAAAAAAAAAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAAAAAAAAAAABAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEAAAAAAAAAAAEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQAAAAAAAAAAAQEBAQEBAQEBAQEBAAAAAAAAAAAAAAAAAAAAAAAAAAABAQEBAQEBAQEBAQEAAAAAAAAAAAAAAAAAAAAAAAAAAAEBAQEBAQEBAQEBAQAAAAAAAAAAAAAAAAAAAAAAAAAAAQEBAQEBAQEBAQEBAAAAAAAAAAAAAAAAAAAAAAAAAAABAQEBAQEBAQEBAQEAAAAAAAAAAAAAAAAAAAAAAAAAAAEBAQEBAQEBAQEBAQAAAAAAAAAAAAAAAAAAAAAAAAAAAQEBAQEBAQEBAQEBAAAAAAAAAAAAAAAAAAAAAAAAAAABAQEBAQEBAQEBAQEAAAAAAAAAAAAAAAAAAAAAAAAAAAEBAQEBAQEBAQEBAQAAAAAAAAAAAAAAAAAAAQEBAQEBAQEBAQEBAQEBAQEBAAAAAAAAAAAAAAAAAAABAQEBAQEBAQEBAQEBAQEBAQEAAAAAAAAAAAAAAAAAAAEBAQEBAQEBAQEBAQEBAQEBAQAAAAAAAAAAAAAAAAAAAQEBAQEBAQEBAQEBAAAAAAAAAAAAAAAAAAAAAAAAAAABAQEBAQEBAQEBAQEAAAAAAAAAAAAAAAAAAAAAAAAAAAEBAQEBAQEBAQEBAQAAAAAAAAAAAAAAAAAAAQEBAQEBAQEBAQEBAQEBAQEBAAAAAAAAAAAAAAAAAAABAQEBAQEBAQEBAQEBAQEBAQEAAAAAAAAAAAAAAAAAAAEBAQEBAQEBAQEBAQEBAQEBAQAAAAAAAAAAAAAAAAAAAQEBAQEBAQEBAQEBAQEBAQEBAAAAAAAAAAAAAAAAAAABAQEBAQEBAQEBAQEBAQEBAQEAAAAAAAAAAAAAAAAAAAEBAQEBAQEBAQEBAQ==" - }, - "palette" : { - "originalArgb8888" : [ -265674 ], - "convertedRgb565" : [ -122 ] } }, "diagnostics" : [ ] @@ -186,14 +186,14 @@ "last_modified" : 1774359772416, "fingerprint" : "eeb7cc665386299403b7be1c272375d5077f3647c587f8033aa8c9275f840562", "metadata" : { + "palette" : { + "originalArgb8888" : [ -265674 ], + "convertedRgb565" : [ -122 ] + }, "tile" : { "width" : 32, "height" : 32, "paletteIndices" : "AQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAAAAAAAAAAABAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEAAAAAAAAAAAEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQAAAAAAAAAAAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAAAAAAAAAAABAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEAAAAAAAAAAAEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQAAAAAAAAAAAQEBAQEBAQEBAQEBAAAAAAAAAAAAAAAAAAAAAAAAAAABAQEBAQEBAQEBAQEAAAAAAAAAAAAAAAAAAAAAAAAAAAEBAQEBAQEBAQEBAQAAAAAAAAAAAAAAAAAAAAAAAAAAAQEBAQEBAQEBAQEBAAAAAAAAAAAAAAAAAAAAAAAAAAABAQEBAQEBAQEBAQEAAAAAAAAAAAAAAAAAAAAAAAAAAAEBAQEBAQEBAQEBAQAAAAAAAAAAAAAAAAAAAAAAAAAAAQEBAQEBAQEBAQEBAAAAAAAAAAAAAAAAAAAAAAAAAAABAQEBAQEBAQEBAQEAAAAAAAAAAAAAAAAAAAAAAAAAAAEBAQEBAQEBAQEBAQAAAAAAAAAAAAAAAAAAAQEBAQEBAQEBAQEBAQEBAQEBAAAAAAAAAAAAAAAAAAABAQEBAQEBAQEBAQEBAQEBAQEAAAAAAAAAAAAAAAAAAAEBAQEBAQEBAQEBAQEBAQEBAQAAAAAAAAAAAAAAAAAAAQEBAQEBAQEBAQEBAAAAAAAAAAAAAAAAAAAAAAAAAAABAQEBAQEBAQEBAQEAAAAAAAAAAAAAAAAAAAAAAAAAAAEBAQEBAQEBAQEBAQAAAAAAAAAAAAAAAAAAAQEBAQEBAQEBAQEBAQEBAQEBAAAAAAAAAAAAAAAAAAABAQEBAQEBAQEBAQEBAQEBAQEAAAAAAAAAAAAAAAAAAAEBAQEBAQEBAQEBAQEBAQEBAQAAAAAAAAAAAAAAAAAAAQEBAQEBAQEBAQEBAQEBAQEBAAAAAAAAAAAAAAAAAAABAQEBAQEBAQEBAQEBAQEBAQEAAAAAAAAAAAAAAAAAAAEBAQEBAQEBAQEBAQ==" - }, - "palette" : { - "originalArgb8888" : [ -265674 ], - "convertedRgb565" : [ -122 ] } }, "diagnostics" : [ ] @@ -204,14 +204,14 @@ "last_modified" : 1774359772417, "fingerprint" : "eeb7cc665386299403b7be1c272375d5077f3647c587f8033aa8c9275f840562", "metadata" : { + "palette" : { + "originalArgb8888" : [ -265674 ], + "convertedRgb565" : [ -122 ] + }, "tile" : { "width" : 32, "height" : 32, "paletteIndices" : "AQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAAAAAAAAAAABAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEAAAAAAAAAAAEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQAAAAAAAAAAAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAAAAAAAAAAABAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEAAAAAAAAAAAEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQAAAAAAAAAAAQEBAQEBAQEBAQEBAAAAAAAAAAAAAAAAAAAAAAAAAAABAQEBAQEBAQEBAQEAAAAAAAAAAAAAAAAAAAAAAAAAAAEBAQEBAQEBAQEBAQAAAAAAAAAAAAAAAAAAAAAAAAAAAQEBAQEBAQEBAQEBAAAAAAAAAAAAAAAAAAAAAAAAAAABAQEBAQEBAQEBAQEAAAAAAAAAAAAAAAAAAAAAAAAAAAEBAQEBAQEBAQEBAQAAAAAAAAAAAAAAAAAAAAAAAAAAAQEBAQEBAQEBAQEBAAAAAAAAAAAAAAAAAAAAAAAAAAABAQEBAQEBAQEBAQEAAAAAAAAAAAAAAAAAAAAAAAAAAAEBAQEBAQEBAQEBAQAAAAAAAAAAAAAAAAAAAQEBAQEBAQEBAQEBAQEBAQEBAAAAAAAAAAAAAAAAAAABAQEBAQEBAQEBAQEBAQEBAQEAAAAAAAAAAAAAAAAAAAEBAQEBAQEBAQEBAQEBAQEBAQAAAAAAAAAAAAAAAAAAAQEBAQEBAQEBAQEBAAAAAAAAAAAAAAAAAAAAAAAAAAABAQEBAQEBAQEBAQEAAAAAAAAAAAAAAAAAAAAAAAAAAAEBAQEBAQEBAQEBAQAAAAAAAAAAAAAAAAAAAQEBAQEBAQEBAQEBAQEBAQEBAAAAAAAAAAAAAAAAAAABAQEBAQEBAQEBAQEBAQEBAQEAAAAAAAAAAAAAAAAAAAEBAQEBAQEBAQEBAQEBAQEBAQAAAAAAAAAAAAAAAAAAAQEBAQEBAQEBAQEBAQEBAQEBAAAAAAAAAAAAAAAAAAABAQEBAQEBAQEBAQEBAQEBAQEAAAAAAAAAAAAAAAAAAAEBAQEBAQEBAQEBAQ==" - }, - "palette" : { - "originalArgb8888" : [ -265674 ], - "convertedRgb565" : [ -122 ] } }, "diagnostics" : [ ] @@ -222,14 +222,14 @@ "last_modified" : 1774359772418, "fingerprint" : "eeb7cc665386299403b7be1c272375d5077f3647c587f8033aa8c9275f840562", "metadata" : { + "palette" : { + "originalArgb8888" : [ -265674 ], + "convertedRgb565" : [ -122 ] + }, "tile" : { "width" : 32, "height" : 32, "paletteIndices" : "AQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAAAAAAAAAAABAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEAAAAAAAAAAAEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQAAAAAAAAAAAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAAAAAAAAAAABAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEAAAAAAAAAAAEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQAAAAAAAAAAAQEBAQEBAQEBAQEBAAAAAAAAAAAAAAAAAAAAAAAAAAABAQEBAQEBAQEBAQEAAAAAAAAAAAAAAAAAAAAAAAAAAAEBAQEBAQEBAQEBAQAAAAAAAAAAAAAAAAAAAAAAAAAAAQEBAQEBAQEBAQEBAAAAAAAAAAAAAAAAAAAAAAAAAAABAQEBAQEBAQEBAQEAAAAAAAAAAAAAAAAAAAAAAAAAAAEBAQEBAQEBAQEBAQAAAAAAAAAAAAAAAAAAAAAAAAAAAQEBAQEBAQEBAQEBAAAAAAAAAAAAAAAAAAAAAAAAAAABAQEBAQEBAQEBAQEAAAAAAAAAAAAAAAAAAAAAAAAAAAEBAQEBAQEBAQEBAQAAAAAAAAAAAAAAAAAAAQEBAQEBAQEBAQEBAQEBAQEBAAAAAAAAAAAAAAAAAAABAQEBAQEBAQEBAQEBAQEBAQEAAAAAAAAAAAAAAAAAAAEBAQEBAQEBAQEBAQEBAQEBAQAAAAAAAAAAAAAAAAAAAQEBAQEBAQEBAQEBAAAAAAAAAAAAAAAAAAAAAAAAAAABAQEBAQEBAQEBAQEAAAAAAAAAAAAAAAAAAAAAAAAAAAEBAQEBAQEBAQEBAQAAAAAAAAAAAAAAAAAAAQEBAQEBAQEBAQEBAQEBAQEBAAAAAAAAAAAAAAAAAAABAQEBAQEBAQEBAQEBAQEBAQEAAAAAAAAAAAAAAAAAAAEBAQEBAQEBAQEBAQEBAQEBAQAAAAAAAAAAAAAAAAAAAQEBAQEBAQEBAQEBAQEBAQEBAAAAAAAAAAAAAAAAAAABAQEBAQEBAQEBAQEBAQEBAQEAAAAAAAAAAAAAAAAAAAEBAQEBAQEBAQEBAQ==" - }, - "palette" : { - "originalArgb8888" : [ -265674 ], - "convertedRgb565" : [ -122 ] } }, "diagnostics" : [ ] @@ -240,14 +240,14 @@ "last_modified" : 1774359772420, "fingerprint" : "eeb7cc665386299403b7be1c272375d5077f3647c587f8033aa8c9275f840562", "metadata" : { + "palette" : { + "originalArgb8888" : [ -265674 ], + "convertedRgb565" : [ -122 ] + }, "tile" : { "width" : 32, "height" : 32, "paletteIndices" : "AQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAAAAAAAAAAABAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEAAAAAAAAAAAEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQAAAAAAAAAAAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAAAAAAAAAAABAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEAAAAAAAAAAAEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQAAAAAAAAAAAQEBAQEBAQEBAQEBAAAAAAAAAAAAAAAAAAAAAAAAAAABAQEBAQEBAQEBAQEAAAAAAAAAAAAAAAAAAAAAAAAAAAEBAQEBAQEBAQEBAQAAAAAAAAAAAAAAAAAAAAAAAAAAAQEBAQEBAQEBAQEBAAAAAAAAAAAAAAAAAAAAAAAAAAABAQEBAQEBAQEBAQEAAAAAAAAAAAAAAAAAAAAAAAAAAAEBAQEBAQEBAQEBAQAAAAAAAAAAAAAAAAAAAAAAAAAAAQEBAQEBAQEBAQEBAAAAAAAAAAAAAAAAAAAAAAAAAAABAQEBAQEBAQEBAQEAAAAAAAAAAAAAAAAAAAAAAAAAAAEBAQEBAQEBAQEBAQAAAAAAAAAAAAAAAAAAAQEBAQEBAQEBAQEBAQEBAQEBAAAAAAAAAAAAAAAAAAABAQEBAQEBAQEBAQEBAQEBAQEAAAAAAAAAAAAAAAAAAAEBAQEBAQEBAQEBAQEBAQEBAQAAAAAAAAAAAAAAAAAAAQEBAQEBAQEBAQEBAAAAAAAAAAAAAAAAAAAAAAAAAAABAQEBAQEBAQEBAQEAAAAAAAAAAAAAAAAAAAAAAAAAAAEBAQEBAQEBAQEBAQAAAAAAAAAAAAAAAAAAAQEBAQEBAQEBAQEBAQEBAQEBAAAAAAAAAAAAAAAAAAABAQEBAQEBAQEBAQEBAQEBAQEAAAAAAAAAAAAAAAAAAAEBAQEBAQEBAQEBAQEBAQEBAQAAAAAAAAAAAAAAAAAAAQEBAQEBAQEBAQEBAQEBAQEBAAAAAAAAAAAAAAAAAAABAQEBAQEBAQEBAQEBAQEBAQEAAAAAAAAAAAAAAAAAAAEBAQEBAQEBAQEBAQ==" - }, - "palette" : { - "originalArgb8888" : [ -265674 ], - "convertedRgb565" : [ -122 ] } }, "diagnostics" : [ ] @@ -258,14 +258,14 @@ "last_modified" : 1774359772421, "fingerprint" : "eeb7cc665386299403b7be1c272375d5077f3647c587f8033aa8c9275f840562", "metadata" : { + "palette" : { + "originalArgb8888" : [ -265674 ], + "convertedRgb565" : [ -122 ] + }, "tile" : { "width" : 32, "height" : 32, "paletteIndices" : "AQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAAAAAAAAAAABAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEAAAAAAAAAAAEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQAAAAAAAAAAAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAAAAAAAAAAABAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEAAAAAAAAAAAEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQAAAAAAAAAAAQEBAQEBAQEBAQEBAAAAAAAAAAAAAAAAAAAAAAAAAAABAQEBAQEBAQEBAQEAAAAAAAAAAAAAAAAAAAAAAAAAAAEBAQEBAQEBAQEBAQAAAAAAAAAAAAAAAAAAAAAAAAAAAQEBAQEBAQEBAQEBAAAAAAAAAAAAAAAAAAAAAAAAAAABAQEBAQEBAQEBAQEAAAAAAAAAAAAAAAAAAAAAAAAAAAEBAQEBAQEBAQEBAQAAAAAAAAAAAAAAAAAAAAAAAAAAAQEBAQEBAQEBAQEBAAAAAAAAAAAAAAAAAAAAAAAAAAABAQEBAQEBAQEBAQEAAAAAAAAAAAAAAAAAAAAAAAAAAAEBAQEBAQEBAQEBAQAAAAAAAAAAAAAAAAAAAQEBAQEBAQEBAQEBAQEBAQEBAAAAAAAAAAAAAAAAAAABAQEBAQEBAQEBAQEBAQEBAQEAAAAAAAAAAAAAAAAAAAEBAQEBAQEBAQEBAQEBAQEBAQAAAAAAAAAAAAAAAAAAAQEBAQEBAQEBAQEBAAAAAAAAAAAAAAAAAAAAAAAAAAABAQEBAQEBAQEBAQEAAAAAAAAAAAAAAAAAAAAAAAAAAAEBAQEBAQEBAQEBAQAAAAAAAAAAAAAAAAAAAQEBAQEBAQEBAQEBAQEBAQEBAAAAAAAAAAAAAAAAAAABAQEBAQEBAQEBAQEBAQEBAQEAAAAAAAAAAAAAAAAAAAEBAQEBAQEBAQEBAQEBAQEBAQAAAAAAAAAAAAAAAAAAAQEBAQEBAQEBAQEBAQEBAQEBAAAAAAAAAAAAAAAAAAABAQEBAQEBAQEBAQEBAQEBAQEAAAAAAAAAAAAAAAAAAAEBAQEBAQEBAQEBAQ==" - }, - "palette" : { - "originalArgb8888" : [ -265674 ], - "convertedRgb565" : [ -122 ] } }, "diagnostics" : [ ] @@ -276,14 +276,14 @@ "last_modified" : 1774359772423, "fingerprint" : "eeb7cc665386299403b7be1c272375d5077f3647c587f8033aa8c9275f840562", "metadata" : { + "palette" : { + "originalArgb8888" : [ -265674 ], + "convertedRgb565" : [ -122 ] + }, "tile" : { "width" : 32, "height" : 32, "paletteIndices" : "AQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAAAAAAAAAAABAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEAAAAAAAAAAAEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQAAAAAAAAAAAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAAAAAAAAAAABAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEAAAAAAAAAAAEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQAAAAAAAAAAAQEBAQEBAQEBAQEBAAAAAAAAAAAAAAAAAAAAAAAAAAABAQEBAQEBAQEBAQEAAAAAAAAAAAAAAAAAAAAAAAAAAAEBAQEBAQEBAQEBAQAAAAAAAAAAAAAAAAAAAAAAAAAAAQEBAQEBAQEBAQEBAAAAAAAAAAAAAAAAAAAAAAAAAAABAQEBAQEBAQEBAQEAAAAAAAAAAAAAAAAAAAAAAAAAAAEBAQEBAQEBAQEBAQAAAAAAAAAAAAAAAAAAAAAAAAAAAQEBAQEBAQEBAQEBAAAAAAAAAAAAAAAAAAAAAAAAAAABAQEBAQEBAQEBAQEAAAAAAAAAAAAAAAAAAAAAAAAAAAEBAQEBAQEBAQEBAQAAAAAAAAAAAAAAAAAAAQEBAQEBAQEBAQEBAQEBAQEBAAAAAAAAAAAAAAAAAAABAQEBAQEBAQEBAQEBAQEBAQEAAAAAAAAAAAAAAAAAAAEBAQEBAQEBAQEBAQEBAQEBAQAAAAAAAAAAAAAAAAAAAQEBAQEBAQEBAQEBAAAAAAAAAAAAAAAAAAAAAAAAAAABAQEBAQEBAQEBAQEAAAAAAAAAAAAAAAAAAAAAAAAAAAEBAQEBAQEBAQEBAQAAAAAAAAAAAAAAAAAAAQEBAQEBAQEBAQEBAQEBAQEBAAAAAAAAAAAAAAAAAAABAQEBAQEBAQEBAQEBAQEBAQEAAAAAAAAAAAAAAAAAAAEBAQEBAQEBAQEBAQEBAQEBAQAAAAAAAAAAAAAAAAAAAQEBAQEBAQEBAQEBAQEBAQEBAAAAAAAAAAAAAAAAAAABAQEBAQEBAQEBAQEBAQEBAQEAAAAAAAAAAAAAAAAAAAEBAQEBAQEBAQEBAQ==" - }, - "palette" : { - "originalArgb8888" : [ -265674 ], - "convertedRgb565" : [ -122 ] } }, "diagnostics" : [ ] @@ -294,14 +294,14 @@ "last_modified" : 1774359772424, "fingerprint" : "eeb7cc665386299403b7be1c272375d5077f3647c587f8033aa8c9275f840562", "metadata" : { + "palette" : { + "originalArgb8888" : [ -265674 ], + "convertedRgb565" : [ -122 ] + }, "tile" : { "width" : 32, "height" : 32, "paletteIndices" : "AQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAAAAAAAAAAABAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEAAAAAAAAAAAEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQAAAAAAAAAAAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAAAAAAAAAAABAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEAAAAAAAAAAAEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQAAAAAAAAAAAQEBAQEBAQEBAQEBAAAAAAAAAAAAAAAAAAAAAAAAAAABAQEBAQEBAQEBAQEAAAAAAAAAAAAAAAAAAAAAAAAAAAEBAQEBAQEBAQEBAQAAAAAAAAAAAAAAAAAAAAAAAAAAAQEBAQEBAQEBAQEBAAAAAAAAAAAAAAAAAAAAAAAAAAABAQEBAQEBAQEBAQEAAAAAAAAAAAAAAAAAAAAAAAAAAAEBAQEBAQEBAQEBAQAAAAAAAAAAAAAAAAAAAAAAAAAAAQEBAQEBAQEBAQEBAAAAAAAAAAAAAAAAAAAAAAAAAAABAQEBAQEBAQEBAQEAAAAAAAAAAAAAAAAAAAAAAAAAAAEBAQEBAQEBAQEBAQAAAAAAAAAAAAAAAAAAAQEBAQEBAQEBAQEBAQEBAQEBAAAAAAAAAAAAAAAAAAABAQEBAQEBAQEBAQEBAQEBAQEAAAAAAAAAAAAAAAAAAAEBAQEBAQEBAQEBAQEBAQEBAQAAAAAAAAAAAAAAAAAAAQEBAQEBAQEBAQEBAAAAAAAAAAAAAAAAAAAAAAAAAAABAQEBAQEBAQEBAQEAAAAAAAAAAAAAAAAAAAAAAAAAAAEBAQEBAQEBAQEBAQAAAAAAAAAAAAAAAAAAAQEBAQEBAQEBAQEBAQEBAQEBAAAAAAAAAAAAAAAAAAABAQEBAQEBAQEBAQEBAQEBAQEAAAAAAAAAAAAAAAAAAAEBAQEBAQEBAQEBAQEBAQEBAQAAAAAAAAAAAAAAAAAAAQEBAQEBAQEBAQEBAQEBAQEBAAAAAAAAAAAAAAAAAAABAQEBAQEBAQEBAQEBAQEBAQEAAAAAAAAAAAAAAAAAAAEBAQEBAQEBAQEBAQ==" - }, - "palette" : { - "originalArgb8888" : [ -265674 ], - "convertedRgb565" : [ -122 ] } }, "diagnostics" : [ ] @@ -312,14 +312,14 @@ "last_modified" : 1774359772425, "fingerprint" : "eeb7cc665386299403b7be1c272375d5077f3647c587f8033aa8c9275f840562", "metadata" : { + "palette" : { + "originalArgb8888" : [ -265674 ], + "convertedRgb565" : [ -122 ] + }, "tile" : { "width" : 32, "height" : 32, "paletteIndices" : "AQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAAAAAAAAAAABAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEAAAAAAAAAAAEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQAAAAAAAAAAAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAAAAAAAAAAABAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEAAAAAAAAAAAEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQAAAAAAAAAAAQEBAQEBAQEBAQEBAAAAAAAAAAAAAAAAAAAAAAAAAAABAQEBAQEBAQEBAQEAAAAAAAAAAAAAAAAAAAAAAAAAAAEBAQEBAQEBAQEBAQAAAAAAAAAAAAAAAAAAAAAAAAAAAQEBAQEBAQEBAQEBAAAAAAAAAAAAAAAAAAAAAAAAAAABAQEBAQEBAQEBAQEAAAAAAAAAAAAAAAAAAAAAAAAAAAEBAQEBAQEBAQEBAQAAAAAAAAAAAAAAAAAAAAAAAAAAAQEBAQEBAQEBAQEBAAAAAAAAAAAAAAAAAAAAAAAAAAABAQEBAQEBAQEBAQEAAAAAAAAAAAAAAAAAAAAAAAAAAAEBAQEBAQEBAQEBAQAAAAAAAAAAAAAAAAAAAQEBAQEBAQEBAQEBAQEBAQEBAAAAAAAAAAAAAAAAAAABAQEBAQEBAQEBAQEBAQEBAQEAAAAAAAAAAAAAAAAAAAEBAQEBAQEBAQEBAQEBAQEBAQAAAAAAAAAAAAAAAAAAAQEBAQEBAQEBAQEBAAAAAAAAAAAAAAAAAAAAAAAAAAABAQEBAQEBAQEBAQEAAAAAAAAAAAAAAAAAAAAAAAAAAAEBAQEBAQEBAQEBAQAAAAAAAAAAAAAAAAAAAQEBAQEBAQEBAQEBAQEBAQEBAAAAAAAAAAAAAAAAAAABAQEBAQEBAQEBAQEBAQEBAQEAAAAAAAAAAAAAAAAAAAEBAQEBAQEBAQEBAQEBAQEBAQAAAAAAAAAAAAAAAAAAAQEBAQEBAQEBAQEBAQEBAQEBAAAAAAAAAAAAAAAAAAABAQEBAQEBAQEBAQEBAQEBAQEAAAAAAAAAAAAAAAAAAAEBAQEBAQEBAQEBAQ==" - }, - "palette" : { - "originalArgb8888" : [ -265674 ], - "convertedRgb565" : [ -122 ] } }, "diagnostics" : [ ] @@ -330,14 +330,14 @@ "last_modified" : 1774359772426, "fingerprint" : "eeb7cc665386299403b7be1c272375d5077f3647c587f8033aa8c9275f840562", "metadata" : { + "palette" : { + "originalArgb8888" : [ -265674 ], + "convertedRgb565" : [ -122 ] + }, "tile" : { "width" : 32, "height" : 32, "paletteIndices" : "AQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAAAAAAAAAAABAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEAAAAAAAAAAAEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQAAAAAAAAAAAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAAAAAAAAAAABAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEAAAAAAAAAAAEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQAAAAAAAAAAAQEBAQEBAQEBAQEBAAAAAAAAAAAAAAAAAAAAAAAAAAABAQEBAQEBAQEBAQEAAAAAAAAAAAAAAAAAAAAAAAAAAAEBAQEBAQEBAQEBAQAAAAAAAAAAAAAAAAAAAAAAAAAAAQEBAQEBAQEBAQEBAAAAAAAAAAAAAAAAAAAAAAAAAAABAQEBAQEBAQEBAQEAAAAAAAAAAAAAAAAAAAAAAAAAAAEBAQEBAQEBAQEBAQAAAAAAAAAAAAAAAAAAAAAAAAAAAQEBAQEBAQEBAQEBAAAAAAAAAAAAAAAAAAAAAAAAAAABAQEBAQEBAQEBAQEAAAAAAAAAAAAAAAAAAAAAAAAAAAEBAQEBAQEBAQEBAQAAAAAAAAAAAAAAAAAAAQEBAQEBAQEBAQEBAQEBAQEBAAAAAAAAAAAAAAAAAAABAQEBAQEBAQEBAQEBAQEBAQEAAAAAAAAAAAAAAAAAAAEBAQEBAQEBAQEBAQEBAQEBAQAAAAAAAAAAAAAAAAAAAQEBAQEBAQEBAQEBAAAAAAAAAAAAAAAAAAAAAAAAAAABAQEBAQEBAQEBAQEAAAAAAAAAAAAAAAAAAAAAAAAAAAEBAQEBAQEBAQEBAQAAAAAAAAAAAAAAAAAAAQEBAQEBAQEBAQEBAQEBAQEBAAAAAAAAAAAAAAAAAAABAQEBAQEBAQEBAQEBAQEBAQEAAAAAAAAAAAAAAAAAAAEBAQEBAQEBAQEBAQEBAQEBAQAAAAAAAAAAAAAAAAAAAQEBAQEBAQEBAQEBAQEBAQEBAAAAAAAAAAAAAAAAAAABAQEBAQEBAQEBAQEBAQEBAQEAAAAAAAAAAAAAAAAAAAEBAQEBAQEBAQEBAQ==" - }, - "palette" : { - "originalArgb8888" : [ -265674 ], - "convertedRgb565" : [ -122 ] } }, "diagnostics" : [ ] @@ -348,14 +348,14 @@ "last_modified" : 1774359772428, "fingerprint" : "eeb7cc665386299403b7be1c272375d5077f3647c587f8033aa8c9275f840562", "metadata" : { + "palette" : { + "originalArgb8888" : [ -265674 ], + "convertedRgb565" : [ -122 ] + }, "tile" : { "width" : 32, "height" : 32, "paletteIndices" : "AQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAAAAAAAAAAABAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEAAAAAAAAAAAEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQAAAAAAAAAAAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAAAAAAAAAAABAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEAAAAAAAAAAAEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQAAAAAAAAAAAQEBAQEBAQEBAQEBAAAAAAAAAAAAAAAAAAAAAAAAAAABAQEBAQEBAQEBAQEAAAAAAAAAAAAAAAAAAAAAAAAAAAEBAQEBAQEBAQEBAQAAAAAAAAAAAAAAAAAAAAAAAAAAAQEBAQEBAQEBAQEBAAAAAAAAAAAAAAAAAAAAAAAAAAABAQEBAQEBAQEBAQEAAAAAAAAAAAAAAAAAAAAAAAAAAAEBAQEBAQEBAQEBAQAAAAAAAAAAAAAAAAAAAAAAAAAAAQEBAQEBAQEBAQEBAAAAAAAAAAAAAAAAAAAAAAAAAAABAQEBAQEBAQEBAQEAAAAAAAAAAAAAAAAAAAAAAAAAAAEBAQEBAQEBAQEBAQAAAAAAAAAAAAAAAAAAAQEBAQEBAQEBAQEBAQEBAQEBAAAAAAAAAAAAAAAAAAABAQEBAQEBAQEBAQEBAQEBAQEAAAAAAAAAAAAAAAAAAAEBAQEBAQEBAQEBAQEBAQEBAQAAAAAAAAAAAAAAAAAAAQEBAQEBAQEBAQEBAAAAAAAAAAAAAAAAAAAAAAAAAAABAQEBAQEBAQEBAQEAAAAAAAAAAAAAAAAAAAAAAAAAAAEBAQEBAQEBAQEBAQAAAAAAAAAAAAAAAAAAAQEBAQEBAQEBAQEBAQEBAQEBAAAAAAAAAAAAAAAAAAABAQEBAQEBAQEBAQEBAQEBAQEAAAAAAAAAAAAAAAAAAAEBAQEBAQEBAQEBAQEBAQEBAQAAAAAAAAAAAAAAAAAAAQEBAQEBAQEBAQEBAQEBAQEBAAAAAAAAAAAAAAAAAAABAQEBAQEBAQEBAQEBAQEBAQEAAAAAAAAAAAAAAAAAAAEBAQEBAQEBAQEBAQ==" - }, - "palette" : { - "originalArgb8888" : [ -265674 ], - "convertedRgb565" : [ -122 ] } }, "diagnostics" : [ ] @@ -366,14 +366,14 @@ "last_modified" : 1774359772429, "fingerprint" : "eeb7cc665386299403b7be1c272375d5077f3647c587f8033aa8c9275f840562", "metadata" : { + "palette" : { + "originalArgb8888" : [ -265674 ], + "convertedRgb565" : [ -122 ] + }, "tile" : { "width" : 32, "height" : 32, "paletteIndices" : "AQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAAAAAAAAAAABAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEAAAAAAAAAAAEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQAAAAAAAAAAAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAAAAAAAAAAABAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEAAAAAAAAAAAEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQAAAAAAAAAAAQEBAQEBAQEBAQEBAAAAAAAAAAAAAAAAAAAAAAAAAAABAQEBAQEBAQEBAQEAAAAAAAAAAAAAAAAAAAAAAAAAAAEBAQEBAQEBAQEBAQAAAAAAAAAAAAAAAAAAAAAAAAAAAQEBAQEBAQEBAQEBAAAAAAAAAAAAAAAAAAAAAAAAAAABAQEBAQEBAQEBAQEAAAAAAAAAAAAAAAAAAAAAAAAAAAEBAQEBAQEBAQEBAQAAAAAAAAAAAAAAAAAAAAAAAAAAAQEBAQEBAQEBAQEBAAAAAAAAAAAAAAAAAAAAAAAAAAABAQEBAQEBAQEBAQEAAAAAAAAAAAAAAAAAAAAAAAAAAAEBAQEBAQEBAQEBAQAAAAAAAAAAAAAAAAAAAQEBAQEBAQEBAQEBAQEBAQEBAAAAAAAAAAAAAAAAAAABAQEBAQEBAQEBAQEBAQEBAQEAAAAAAAAAAAAAAAAAAAEBAQEBAQEBAQEBAQEBAQEBAQAAAAAAAAAAAAAAAAAAAQEBAQEBAQEBAQEBAAAAAAAAAAAAAAAAAAAAAAAAAAABAQEBAQEBAQEBAQEAAAAAAAAAAAAAAAAAAAAAAAAAAAEBAQEBAQEBAQEBAQAAAAAAAAAAAAAAAAAAAQEBAQEBAQEBAQEBAQEBAQEBAAAAAAAAAAAAAAAAAAABAQEBAQEBAQEBAQEBAQEBAQEAAAAAAAAAAAAAAAAAAAEBAQEBAQEBAQEBAQEBAQEBAQAAAAAAAAAAAAAAAAAAAQEBAQEBAQEBAQEBAQEBAQEBAAAAAAAAAAAAAAAAAAABAQEBAQEBAQEBAQEBAQEBAQEAAAAAAAAAAAAAAAAAAAEBAQEBAQEBAQEBAQ==" - }, - "palette" : { - "originalArgb8888" : [ -265674 ], - "convertedRgb565" : [ -122 ] } }, "diagnostics" : [ ] @@ -384,14 +384,14 @@ "last_modified" : 1774359772430, "fingerprint" : "eeb7cc665386299403b7be1c272375d5077f3647c587f8033aa8c9275f840562", "metadata" : { + "palette" : { + "originalArgb8888" : [ -265674 ], + "convertedRgb565" : [ -122 ] + }, "tile" : { "width" : 32, "height" : 32, "paletteIndices" : "AQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAAAAAAAAAAABAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEAAAAAAAAAAAEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQAAAAAAAAAAAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAAAAAAAAAAABAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEAAAAAAAAAAAEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQAAAAAAAAAAAQEBAQEBAQEBAQEBAAAAAAAAAAAAAAAAAAAAAAAAAAABAQEBAQEBAQEBAQEAAAAAAAAAAAAAAAAAAAAAAAAAAAEBAQEBAQEBAQEBAQAAAAAAAAAAAAAAAAAAAAAAAAAAAQEBAQEBAQEBAQEBAAAAAAAAAAAAAAAAAAAAAAAAAAABAQEBAQEBAQEBAQEAAAAAAAAAAAAAAAAAAAAAAAAAAAEBAQEBAQEBAQEBAQAAAAAAAAAAAAAAAAAAAAAAAAAAAQEBAQEBAQEBAQEBAAAAAAAAAAAAAAAAAAAAAAAAAAABAQEBAQEBAQEBAQEAAAAAAAAAAAAAAAAAAAAAAAAAAAEBAQEBAQEBAQEBAQAAAAAAAAAAAAAAAAAAAQEBAQEBAQEBAQEBAQEBAQEBAAAAAAAAAAAAAAAAAAABAQEBAQEBAQEBAQEBAQEBAQEAAAAAAAAAAAAAAAAAAAEBAQEBAQEBAQEBAQEBAQEBAQAAAAAAAAAAAAAAAAAAAQEBAQEBAQEBAQEBAAAAAAAAAAAAAAAAAAAAAAAAAAABAQEBAQEBAQEBAQEAAAAAAAAAAAAAAAAAAAAAAAAAAAEBAQEBAQEBAQEBAQAAAAAAAAAAAAAAAAAAAQEBAQEBAQEBAQEBAQEBAQEBAAAAAAAAAAAAAAAAAAABAQEBAQEBAQEBAQEBAQEBAQEAAAAAAAAAAAAAAAAAAAEBAQEBAQEBAQEBAQEBAQEBAQAAAAAAAAAAAAAAAAAAAQEBAQEBAQEBAQEBAQEBAQEBAAAAAAAAAAAAAAAAAAABAQEBAQEBAQEBAQEBAQEBAQEAAAAAAAAAAAAAAAAAAAEBAQEBAQEBAQEBAQ==" - }, - "palette" : { - "originalArgb8888" : [ -265674 ], - "convertedRgb565" : [ -122 ] } }, "diagnostics" : [ ] @@ -402,14 +402,14 @@ "last_modified" : 1774359772431, "fingerprint" : "eeb7cc665386299403b7be1c272375d5077f3647c587f8033aa8c9275f840562", "metadata" : { + "palette" : { + "originalArgb8888" : [ -265674 ], + "convertedRgb565" : [ -122 ] + }, "tile" : { "width" : 32, "height" : 32, "paletteIndices" : "AQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAAAAAAAAAAABAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEAAAAAAAAAAAEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQAAAAAAAAAAAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAAAAAAAAAAABAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEAAAAAAAAAAAEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQAAAAAAAAAAAQEBAQEBAQEBAQEBAAAAAAAAAAAAAAAAAAAAAAAAAAABAQEBAQEBAQEBAQEAAAAAAAAAAAAAAAAAAAAAAAAAAAEBAQEBAQEBAQEBAQAAAAAAAAAAAAAAAAAAAAAAAAAAAQEBAQEBAQEBAQEBAAAAAAAAAAAAAAAAAAAAAAAAAAABAQEBAQEBAQEBAQEAAAAAAAAAAAAAAAAAAAAAAAAAAAEBAQEBAQEBAQEBAQAAAAAAAAAAAAAAAAAAAAAAAAAAAQEBAQEBAQEBAQEBAAAAAAAAAAAAAAAAAAAAAAAAAAABAQEBAQEBAQEBAQEAAAAAAAAAAAAAAAAAAAAAAAAAAAEBAQEBAQEBAQEBAQAAAAAAAAAAAAAAAAAAAQEBAQEBAQEBAQEBAQEBAQEBAAAAAAAAAAAAAAAAAAABAQEBAQEBAQEBAQEBAQEBAQEAAAAAAAAAAAAAAAAAAAEBAQEBAQEBAQEBAQEBAQEBAQAAAAAAAAAAAAAAAAAAAQEBAQEBAQEBAQEBAAAAAAAAAAAAAAAAAAAAAAAAAAABAQEBAQEBAQEBAQEAAAAAAAAAAAAAAAAAAAAAAAAAAAEBAQEBAQEBAQEBAQAAAAAAAAAAAAAAAAAAAQEBAQEBAQEBAQEBAQEBAQEBAAAAAAAAAAAAAAAAAAABAQEBAQEBAQEBAQEBAQEBAQEAAAAAAAAAAAAAAAAAAAEBAQEBAQEBAQEBAQEBAQEBAQAAAAAAAAAAAAAAAAAAAQEBAQEBAQEBAQEBAQEBAQEBAAAAAAAAAAAAAAAAAAABAQEBAQEBAQEBAQEBAQEBAQEAAAAAAAAAAAAAAAAAAAEBAQEBAQEBAQEBAQ==" - }, - "palette" : { - "originalArgb8888" : [ -265674 ], - "convertedRgb565" : [ -122 ] } }, "diagnostics" : [ ] @@ -420,14 +420,14 @@ "last_modified" : 1774359772432, "fingerprint" : "eeb7cc665386299403b7be1c272375d5077f3647c587f8033aa8c9275f840562", "metadata" : { + "palette" : { + "originalArgb8888" : [ -265674 ], + "convertedRgb565" : [ -122 ] + }, "tile" : { "width" : 32, "height" : 32, "paletteIndices" : "AQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAAAAAAAAAAABAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEAAAAAAAAAAAEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQAAAAAAAAAAAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAAAAAAAAAAABAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEAAAAAAAAAAAEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQAAAAAAAAAAAQEBAQEBAQEBAQEBAAAAAAAAAAAAAAAAAAAAAAAAAAABAQEBAQEBAQEBAQEAAAAAAAAAAAAAAAAAAAAAAAAAAAEBAQEBAQEBAQEBAQAAAAAAAAAAAAAAAAAAAAAAAAAAAQEBAQEBAQEBAQEBAAAAAAAAAAAAAAAAAAAAAAAAAAABAQEBAQEBAQEBAQEAAAAAAAAAAAAAAAAAAAAAAAAAAAEBAQEBAQEBAQEBAQAAAAAAAAAAAAAAAAAAAAAAAAAAAQEBAQEBAQEBAQEBAAAAAAAAAAAAAAAAAAAAAAAAAAABAQEBAQEBAQEBAQEAAAAAAAAAAAAAAAAAAAAAAAAAAAEBAQEBAQEBAQEBAQAAAAAAAAAAAAAAAAAAAQEBAQEBAQEBAQEBAQEBAQEBAAAAAAAAAAAAAAAAAAABAQEBAQEBAQEBAQEBAQEBAQEAAAAAAAAAAAAAAAAAAAEBAQEBAQEBAQEBAQEBAQEBAQAAAAAAAAAAAAAAAAAAAQEBAQEBAQEBAQEBAAAAAAAAAAAAAAAAAAAAAAAAAAABAQEBAQEBAQEBAQEAAAAAAAAAAAAAAAAAAAAAAAAAAAEBAQEBAQEBAQEBAQAAAAAAAAAAAAAAAAAAAQEBAQEBAQEBAQEBAQEBAQEBAAAAAAAAAAAAAAAAAAABAQEBAQEBAQEBAQEBAQEBAQEAAAAAAAAAAAAAAAAAAAEBAQEBAQEBAQEBAQEBAQEBAQAAAAAAAAAAAAAAAAAAAQEBAQEBAQEBAQEBAQEBAQEBAAAAAAAAAAAAAAAAAAABAQEBAQEBAQEBAQEBAQEBAQEAAAAAAAAAAAAAAAAAAAEBAQEBAQEBAQEBAQ==" - }, - "palette" : { - "originalArgb8888" : [ -265674 ], - "convertedRgb565" : [ -122 ] } }, "diagnostics" : [ ] @@ -438,14 +438,14 @@ "last_modified" : 1774359772433, "fingerprint" : "eeb7cc665386299403b7be1c272375d5077f3647c587f8033aa8c9275f840562", "metadata" : { + "palette" : { + "originalArgb8888" : [ -265674 ], + "convertedRgb565" : [ -122 ] + }, "tile" : { "width" : 32, "height" : 32, "paletteIndices" : "AQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAAAAAAAAAAABAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEAAAAAAAAAAAEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQAAAAAAAAAAAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAAAAAAAAAAABAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEAAAAAAAAAAAEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQAAAAAAAAAAAQEBAQEBAQEBAQEBAAAAAAAAAAAAAAAAAAAAAAAAAAABAQEBAQEBAQEBAQEAAAAAAAAAAAAAAAAAAAAAAAAAAAEBAQEBAQEBAQEBAQAAAAAAAAAAAAAAAAAAAAAAAAAAAQEBAQEBAQEBAQEBAAAAAAAAAAAAAAAAAAAAAAAAAAABAQEBAQEBAQEBAQEAAAAAAAAAAAAAAAAAAAAAAAAAAAEBAQEBAQEBAQEBAQAAAAAAAAAAAAAAAAAAAAAAAAAAAQEBAQEBAQEBAQEBAAAAAAAAAAAAAAAAAAAAAAAAAAABAQEBAQEBAQEBAQEAAAAAAAAAAAAAAAAAAAAAAAAAAAEBAQEBAQEBAQEBAQAAAAAAAAAAAAAAAAAAAQEBAQEBAQEBAQEBAQEBAQEBAAAAAAAAAAAAAAAAAAABAQEBAQEBAQEBAQEBAQEBAQEAAAAAAAAAAAAAAAAAAAEBAQEBAQEBAQEBAQEBAQEBAQAAAAAAAAAAAAAAAAAAAQEBAQEBAQEBAQEBAAAAAAAAAAAAAAAAAAAAAAAAAAABAQEBAQEBAQEBAQEAAAAAAAAAAAAAAAAAAAAAAAAAAAEBAQEBAQEBAQEBAQAAAAAAAAAAAAAAAAAAAQEBAQEBAQEBAQEBAQEBAQEBAAAAAAAAAAAAAAAAAAABAQEBAQEBAQEBAQEBAQEBAQEAAAAAAAAAAAAAAAAAAAEBAQEBAQEBAQEBAQEBAQEBAQAAAAAAAAAAAAAAAAAAAQEBAQEBAQEBAQEBAQEBAQEBAAAAAAAAAAAAAAAAAAABAQEBAQEBAQEBAQEBAQEBAQEAAAAAAAAAAAAAAAAAAAEBAQEBAQEBAQEBAQ==" - }, - "palette" : { - "originalArgb8888" : [ -265674 ], - "convertedRgb565" : [ -122 ] } }, "diagnostics" : [ ] @@ -456,14 +456,14 @@ "last_modified" : 1774359772435, "fingerprint" : "eeb7cc665386299403b7be1c272375d5077f3647c587f8033aa8c9275f840562", "metadata" : { + "palette" : { + "originalArgb8888" : [ -265674 ], + "convertedRgb565" : [ -122 ] + }, "tile" : { "width" : 32, "height" : 32, "paletteIndices" : "AQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAAAAAAAAAAABAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEAAAAAAAAAAAEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQAAAAAAAAAAAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAAAAAAAAAAABAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEAAAAAAAAAAAEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQAAAAAAAAAAAQEBAQEBAQEBAQEBAAAAAAAAAAAAAAAAAAAAAAAAAAABAQEBAQEBAQEBAQEAAAAAAAAAAAAAAAAAAAAAAAAAAAEBAQEBAQEBAQEBAQAAAAAAAAAAAAAAAAAAAAAAAAAAAQEBAQEBAQEBAQEBAAAAAAAAAAAAAAAAAAAAAAAAAAABAQEBAQEBAQEBAQEAAAAAAAAAAAAAAAAAAAAAAAAAAAEBAQEBAQEBAQEBAQAAAAAAAAAAAAAAAAAAAAAAAAAAAQEBAQEBAQEBAQEBAAAAAAAAAAAAAAAAAAAAAAAAAAABAQEBAQEBAQEBAQEAAAAAAAAAAAAAAAAAAAAAAAAAAAEBAQEBAQEBAQEBAQAAAAAAAAAAAAAAAAAAAQEBAQEBAQEBAQEBAQEBAQEBAAAAAAAAAAAAAAAAAAABAQEBAQEBAQEBAQEBAQEBAQEAAAAAAAAAAAAAAAAAAAEBAQEBAQEBAQEBAQEBAQEBAQAAAAAAAAAAAAAAAAAAAQEBAQEBAQEBAQEBAAAAAAAAAAAAAAAAAAAAAAAAAAABAQEBAQEBAQEBAQEAAAAAAAAAAAAAAAAAAAAAAAAAAAEBAQEBAQEBAQEBAQAAAAAAAAAAAAAAAAAAAQEBAQEBAQEBAQEBAQEBAQEBAAAAAAAAAAAAAAAAAAABAQEBAQEBAQEBAQEBAQEBAQEAAAAAAAAAAAAAAAAAAAEBAQEBAQEBAQEBAQEBAQEBAQAAAAAAAAAAAAAAAAAAAQEBAQEBAQEBAQEBAQEBAQEBAAAAAAAAAAAAAAAAAAABAQEBAQEBAQEBAQEBAQEBAQEAAAAAAAAAAAAAAAAAAAEBAQEBAQEBAQEBAQ==" - }, - "palette" : { - "originalArgb8888" : [ -265674 ], - "convertedRgb565" : [ -122 ] } }, "diagnostics" : [ ] @@ -474,14 +474,14 @@ "last_modified" : 1774359772436, "fingerprint" : "eeb7cc665386299403b7be1c272375d5077f3647c587f8033aa8c9275f840562", "metadata" : { + "palette" : { + "originalArgb8888" : [ -265674 ], + "convertedRgb565" : [ -122 ] + }, "tile" : { "width" : 32, "height" : 32, "paletteIndices" : "AQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAAAAAAAAAAABAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEAAAAAAAAAAAEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQAAAAAAAAAAAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAAAAAAAAAAABAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEAAAAAAAAAAAEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQAAAAAAAAAAAQEBAQEBAQEBAQEBAAAAAAAAAAAAAAAAAAAAAAAAAAABAQEBAQEBAQEBAQEAAAAAAAAAAAAAAAAAAAAAAAAAAAEBAQEBAQEBAQEBAQAAAAAAAAAAAAAAAAAAAAAAAAAAAQEBAQEBAQEBAQEBAAAAAAAAAAAAAAAAAAAAAAAAAAABAQEBAQEBAQEBAQEAAAAAAAAAAAAAAAAAAAAAAAAAAAEBAQEBAQEBAQEBAQAAAAAAAAAAAAAAAAAAAAAAAAAAAQEBAQEBAQEBAQEBAAAAAAAAAAAAAAAAAAAAAAAAAAABAQEBAQEBAQEBAQEAAAAAAAAAAAAAAAAAAAAAAAAAAAEBAQEBAQEBAQEBAQAAAAAAAAAAAAAAAAAAAQEBAQEBAQEBAQEBAQEBAQEBAAAAAAAAAAAAAAAAAAABAQEBAQEBAQEBAQEBAQEBAQEAAAAAAAAAAAAAAAAAAAEBAQEBAQEBAQEBAQEBAQEBAQAAAAAAAAAAAAAAAAAAAQEBAQEBAQEBAQEBAAAAAAAAAAAAAAAAAAAAAAAAAAABAQEBAQEBAQEBAQEAAAAAAAAAAAAAAAAAAAAAAAAAAAEBAQEBAQEBAQEBAQAAAAAAAAAAAAAAAAAAAQEBAQEBAQEBAQEBAQEBAQEBAAAAAAAAAAAAAAAAAAABAQEBAQEBAQEBAQEBAQEBAQEAAAAAAAAAAAAAAAAAAAEBAQEBAQEBAQEBAQEBAQEBAQAAAAAAAAAAAAAAAAAAAQEBAQEBAQEBAQEBAQEBAQEBAAAAAAAAAAAAAAAAAAABAQEBAQEBAQEBAQEBAQEBAQEAAAAAAAAAAAAAAAAAAAEBAQEBAQEBAQEBAQ==" - }, - "palette" : { - "originalArgb8888" : [ -265674 ], - "convertedRgb565" : [ -122 ] } }, "diagnostics" : [ ] @@ -492,14 +492,14 @@ "last_modified" : 1774359772437, "fingerprint" : "eeb7cc665386299403b7be1c272375d5077f3647c587f8033aa8c9275f840562", "metadata" : { + "palette" : { + "originalArgb8888" : [ -265674 ], + "convertedRgb565" : [ -122 ] + }, "tile" : { "width" : 32, "height" : 32, "paletteIndices" : "AQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAAAAAAAAAAABAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEAAAAAAAAAAAEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQAAAAAAAAAAAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAAAAAAAAAAABAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEAAAAAAAAAAAEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQAAAAAAAAAAAQEBAQEBAQEBAQEBAAAAAAAAAAAAAAAAAAAAAAAAAAABAQEBAQEBAQEBAQEAAAAAAAAAAAAAAAAAAAAAAAAAAAEBAQEBAQEBAQEBAQAAAAAAAAAAAAAAAAAAAAAAAAAAAQEBAQEBAQEBAQEBAAAAAAAAAAAAAAAAAAAAAAAAAAABAQEBAQEBAQEBAQEAAAAAAAAAAAAAAAAAAAAAAAAAAAEBAQEBAQEBAQEBAQAAAAAAAAAAAAAAAAAAAAAAAAAAAQEBAQEBAQEBAQEBAAAAAAAAAAAAAAAAAAAAAAAAAAABAQEBAQEBAQEBAQEAAAAAAAAAAAAAAAAAAAAAAAAAAAEBAQEBAQEBAQEBAQAAAAAAAAAAAAAAAAAAAQEBAQEBAQEBAQEBAQEBAQEBAAAAAAAAAAAAAAAAAAABAQEBAQEBAQEBAQEBAQEBAQEAAAAAAAAAAAAAAAAAAAEBAQEBAQEBAQEBAQEBAQEBAQAAAAAAAAAAAAAAAAAAAQEBAQEBAQEBAQEBAAAAAAAAAAAAAAAAAAAAAAAAAAABAQEBAQEBAQEBAQEAAAAAAAAAAAAAAAAAAAAAAAAAAAEBAQEBAQEBAQEBAQAAAAAAAAAAAAAAAAAAAQEBAQEBAQEBAQEBAQEBAQEBAAAAAAAAAAAAAAAAAAABAQEBAQEBAQEBAQEBAQEBAQEAAAAAAAAAAAAAAAAAAAEBAQEBAQEBAQEBAQEBAQEBAQAAAAAAAAAAAAAAAAAAAQEBAQEBAQEBAQEBAQEBAQEBAAAAAAAAAAAAAAAAAAABAQEBAQEBAQEBAQEBAQEBAQEAAAAAAAAAAAAAAAAAAAEBAQEBAQEBAQEBAQ==" - }, - "palette" : { - "originalArgb8888" : [ -265674 ], - "convertedRgb565" : [ -122 ] } }, "diagnostics" : [ ] @@ -510,14 +510,14 @@ "last_modified" : 1774359772438, "fingerprint" : "eeb7cc665386299403b7be1c272375d5077f3647c587f8033aa8c9275f840562", "metadata" : { + "palette" : { + "originalArgb8888" : [ -265674 ], + "convertedRgb565" : [ -122 ] + }, "tile" : { "width" : 32, "height" : 32, "paletteIndices" : "AQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAAAAAAAAAAABAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEAAAAAAAAAAAEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQAAAAAAAAAAAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAAAAAAAAAAABAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEAAAAAAAAAAAEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQAAAAAAAAAAAQEBAQEBAQEBAQEBAAAAAAAAAAAAAAAAAAAAAAAAAAABAQEBAQEBAQEBAQEAAAAAAAAAAAAAAAAAAAAAAAAAAAEBAQEBAQEBAQEBAQAAAAAAAAAAAAAAAAAAAAAAAAAAAQEBAQEBAQEBAQEBAAAAAAAAAAAAAAAAAAAAAAAAAAABAQEBAQEBAQEBAQEAAAAAAAAAAAAAAAAAAAAAAAAAAAEBAQEBAQEBAQEBAQAAAAAAAAAAAAAAAAAAAAAAAAAAAQEBAQEBAQEBAQEBAAAAAAAAAAAAAAAAAAAAAAAAAAABAQEBAQEBAQEBAQEAAAAAAAAAAAAAAAAAAAAAAAAAAAEBAQEBAQEBAQEBAQAAAAAAAAAAAAAAAAAAAQEBAQEBAQEBAQEBAQEBAQEBAAAAAAAAAAAAAAAAAAABAQEBAQEBAQEBAQEBAQEBAQEAAAAAAAAAAAAAAAAAAAEBAQEBAQEBAQEBAQEBAQEBAQAAAAAAAAAAAAAAAAAAAQEBAQEBAQEBAQEBAAAAAAAAAAAAAAAAAAAAAAAAAAABAQEBAQEBAQEBAQEAAAAAAAAAAAAAAAAAAAAAAAAAAAEBAQEBAQEBAQEBAQAAAAAAAAAAAAAAAAAAAQEBAQEBAQEBAQEBAQEBAQEBAAAAAAAAAAAAAAAAAAABAQEBAQEBAQEBAQEBAQEBAQEAAAAAAAAAAAAAAAAAAAEBAQEBAQEBAQEBAQEBAQEBAQAAAAAAAAAAAAAAAAAAAQEBAQEBAQEBAQEBAQEBAQEBAAAAAAAAAAAAAAAAAAABAQEBAQEBAQEBAQEBAQEBAQEAAAAAAAAAAAAAAAAAAAEBAQEBAQEBAQEBAQ==" - }, - "palette" : { - "originalArgb8888" : [ -265674 ], - "convertedRgb565" : [ -122 ] } }, "diagnostics" : [ ] @@ -528,14 +528,14 @@ "last_modified" : 1774359772439, "fingerprint" : "eeb7cc665386299403b7be1c272375d5077f3647c587f8033aa8c9275f840562", "metadata" : { + "palette" : { + "originalArgb8888" : [ -265674 ], + "convertedRgb565" : [ -122 ] + }, "tile" : { "width" : 32, "height" : 32, "paletteIndices" : "AQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAAAAAAAAAAABAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEAAAAAAAAAAAEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQAAAAAAAAAAAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAAAAAAAAAAABAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEAAAAAAAAAAAEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQAAAAAAAAAAAQEBAQEBAQEBAQEBAAAAAAAAAAAAAAAAAAAAAAAAAAABAQEBAQEBAQEBAQEAAAAAAAAAAAAAAAAAAAAAAAAAAAEBAQEBAQEBAQEBAQAAAAAAAAAAAAAAAAAAAAAAAAAAAQEBAQEBAQEBAQEBAAAAAAAAAAAAAAAAAAAAAAAAAAABAQEBAQEBAQEBAQEAAAAAAAAAAAAAAAAAAAAAAAAAAAEBAQEBAQEBAQEBAQAAAAAAAAAAAAAAAAAAAAAAAAAAAQEBAQEBAQEBAQEBAAAAAAAAAAAAAAAAAAAAAAAAAAABAQEBAQEBAQEBAQEAAAAAAAAAAAAAAAAAAAAAAAAAAAEBAQEBAQEBAQEBAQAAAAAAAAAAAAAAAAAAAQEBAQEBAQEBAQEBAQEBAQEBAAAAAAAAAAAAAAAAAAABAQEBAQEBAQEBAQEBAQEBAQEAAAAAAAAAAAAAAAAAAAEBAQEBAQEBAQEBAQEBAQEBAQAAAAAAAAAAAAAAAAAAAQEBAQEBAQEBAQEBAAAAAAAAAAAAAAAAAAAAAAAAAAABAQEBAQEBAQEBAQEAAAAAAAAAAAAAAAAAAAAAAAAAAAEBAQEBAQEBAQEBAQAAAAAAAAAAAAAAAAAAAQEBAQEBAQEBAQEBAQEBAQEBAAAAAAAAAAAAAAAAAAABAQEBAQEBAQEBAQEBAQEBAQEAAAAAAAAAAAAAAAAAAAEBAQEBAQEBAQEBAQEBAQEBAQAAAAAAAAAAAAAAAAAAAQEBAQEBAQEBAQEBAQEBAQEBAAAAAAAAAAAAAAAAAAABAQEBAQEBAQEBAQEBAQEBAQEAAAAAAAAAAAAAAAAAAAEBAQEBAQEBAQEBAQ==" - }, - "palette" : { - "originalArgb8888" : [ -265674 ], - "convertedRgb565" : [ -122 ] } }, "diagnostics" : [ ] @@ -546,14 +546,14 @@ "last_modified" : 1774359772441, "fingerprint" : "eeb7cc665386299403b7be1c272375d5077f3647c587f8033aa8c9275f840562", "metadata" : { + "palette" : { + "originalArgb8888" : [ -265674 ], + "convertedRgb565" : [ -122 ] + }, "tile" : { "width" : 32, "height" : 32, "paletteIndices" : "AQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAAAAAAAAAAABAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEAAAAAAAAAAAEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQAAAAAAAAAAAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAAAAAAAAAAABAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEAAAAAAAAAAAEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQAAAAAAAAAAAQEBAQEBAQEBAQEBAAAAAAAAAAAAAAAAAAAAAAAAAAABAQEBAQEBAQEBAQEAAAAAAAAAAAAAAAAAAAAAAAAAAAEBAQEBAQEBAQEBAQAAAAAAAAAAAAAAAAAAAAAAAAAAAQEBAQEBAQEBAQEBAAAAAAAAAAAAAAAAAAAAAAAAAAABAQEBAQEBAQEBAQEAAAAAAAAAAAAAAAAAAAAAAAAAAAEBAQEBAQEBAQEBAQAAAAAAAAAAAAAAAAAAAAAAAAAAAQEBAQEBAQEBAQEBAAAAAAAAAAAAAAAAAAAAAAAAAAABAQEBAQEBAQEBAQEAAAAAAAAAAAAAAAAAAAAAAAAAAAEBAQEBAQEBAQEBAQAAAAAAAAAAAAAAAAAAAQEBAQEBAQEBAQEBAQEBAQEBAAAAAAAAAAAAAAAAAAABAQEBAQEBAQEBAQEBAQEBAQEAAAAAAAAAAAAAAAAAAAEBAQEBAQEBAQEBAQEBAQEBAQAAAAAAAAAAAAAAAAAAAQEBAQEBAQEBAQEBAAAAAAAAAAAAAAAAAAAAAAAAAAABAQEBAQEBAQEBAQEAAAAAAAAAAAAAAAAAAAAAAAAAAAEBAQEBAQEBAQEBAQAAAAAAAAAAAAAAAAAAAQEBAQEBAQEBAQEBAQEBAQEBAAAAAAAAAAAAAAAAAAABAQEBAQEBAQEBAQEBAQEBAQEAAAAAAAAAAAAAAAAAAAEBAQEBAQEBAQEBAQEBAQEBAQAAAAAAAAAAAAAAAAAAAQEBAQEBAQEBAQEBAQEBAQEBAAAAAAAAAAAAAAAAAAABAQEBAQEBAQEBAQEBAQEBAQEAAAAAAAAAAAAAAAAAAAEBAQEBAQEBAQEBAQ==" - }, - "palette" : { - "originalArgb8888" : [ -265674 ], - "convertedRgb565" : [ -122 ] } }, "diagnostics" : [ ] @@ -564,14 +564,14 @@ "last_modified" : 1774359772442, "fingerprint" : "eeb7cc665386299403b7be1c272375d5077f3647c587f8033aa8c9275f840562", "metadata" : { + "palette" : { + "originalArgb8888" : [ -265674 ], + "convertedRgb565" : [ -122 ] + }, "tile" : { "width" : 32, "height" : 32, "paletteIndices" : "AQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAAAAAAAAAAABAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEAAAAAAAAAAAEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQAAAAAAAAAAAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAAAAAAAAAAABAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEAAAAAAAAAAAEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQAAAAAAAAAAAQEBAQEBAQEBAQEBAAAAAAAAAAAAAAAAAAAAAAAAAAABAQEBAQEBAQEBAQEAAAAAAAAAAAAAAAAAAAAAAAAAAAEBAQEBAQEBAQEBAQAAAAAAAAAAAAAAAAAAAAAAAAAAAQEBAQEBAQEBAQEBAAAAAAAAAAAAAAAAAAAAAAAAAAABAQEBAQEBAQEBAQEAAAAAAAAAAAAAAAAAAAAAAAAAAAEBAQEBAQEBAQEBAQAAAAAAAAAAAAAAAAAAAAAAAAAAAQEBAQEBAQEBAQEBAAAAAAAAAAAAAAAAAAAAAAAAAAABAQEBAQEBAQEBAQEAAAAAAAAAAAAAAAAAAAAAAAAAAAEBAQEBAQEBAQEBAQAAAAAAAAAAAAAAAAAAAQEBAQEBAQEBAQEBAQEBAQEBAAAAAAAAAAAAAAAAAAABAQEBAQEBAQEBAQEBAQEBAQEAAAAAAAAAAAAAAAAAAAEBAQEBAQEBAQEBAQEBAQEBAQAAAAAAAAAAAAAAAAAAAQEBAQEBAQEBAQEBAAAAAAAAAAAAAAAAAAAAAAAAAAABAQEBAQEBAQEBAQEAAAAAAAAAAAAAAAAAAAAAAAAAAAEBAQEBAQEBAQEBAQAAAAAAAAAAAAAAAAAAAQEBAQEBAQEBAQEBAQEBAQEBAAAAAAAAAAAAAAAAAAABAQEBAQEBAQEBAQEBAQEBAQEAAAAAAAAAAAAAAAAAAAEBAQEBAQEBAQEBAQEBAQEBAQAAAAAAAAAAAAAAAAAAAQEBAQEBAQEBAQEBAQEBAQEBAAAAAAAAAAAAAAAAAAABAQEBAQEBAQEBAQEBAQEBAQEAAAAAAAAAAAAAAAAAAAEBAQEBAQEBAQEBAQ==" - }, - "palette" : { - "originalArgb8888" : [ -265674 ], - "convertedRgb565" : [ -122 ] } }, "diagnostics" : [ ] @@ -582,14 +582,14 @@ "last_modified" : 1774359772443, "fingerprint" : "eeb7cc665386299403b7be1c272375d5077f3647c587f8033aa8c9275f840562", "metadata" : { + "palette" : { + "originalArgb8888" : [ -265674 ], + "convertedRgb565" : [ -122 ] + }, "tile" : { "width" : 32, "height" : 32, "paletteIndices" : "AQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAAAAAAAAAAABAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEAAAAAAAAAAAEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQAAAAAAAAAAAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAAAAAAAAAAABAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEAAAAAAAAAAAEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQAAAAAAAAAAAQEBAQEBAQEBAQEBAAAAAAAAAAAAAAAAAAAAAAAAAAABAQEBAQEBAQEBAQEAAAAAAAAAAAAAAAAAAAAAAAAAAAEBAQEBAQEBAQEBAQAAAAAAAAAAAAAAAAAAAAAAAAAAAQEBAQEBAQEBAQEBAAAAAAAAAAAAAAAAAAAAAAAAAAABAQEBAQEBAQEBAQEAAAAAAAAAAAAAAAAAAAAAAAAAAAEBAQEBAQEBAQEBAQAAAAAAAAAAAAAAAAAAAAAAAAAAAQEBAQEBAQEBAQEBAAAAAAAAAAAAAAAAAAAAAAAAAAABAQEBAQEBAQEBAQEAAAAAAAAAAAAAAAAAAAAAAAAAAAEBAQEBAQEBAQEBAQAAAAAAAAAAAAAAAAAAAQEBAQEBAQEBAQEBAQEBAQEBAAAAAAAAAAAAAAAAAAABAQEBAQEBAQEBAQEBAQEBAQEAAAAAAAAAAAAAAAAAAAEBAQEBAQEBAQEBAQEBAQEBAQAAAAAAAAAAAAAAAAAAAQEBAQEBAQEBAQEBAAAAAAAAAAAAAAAAAAAAAAAAAAABAQEBAQEBAQEBAQEAAAAAAAAAAAAAAAAAAAAAAAAAAAEBAQEBAQEBAQEBAQAAAAAAAAAAAAAAAAAAAQEBAQEBAQEBAQEBAQEBAQEBAAAAAAAAAAAAAAAAAAABAQEBAQEBAQEBAQEBAQEBAQEAAAAAAAAAAAAAAAAAAAEBAQEBAQEBAQEBAQEBAQEBAQAAAAAAAAAAAAAAAAAAAQEBAQEBAQEBAQEBAQEBAQEBAAAAAAAAAAAAAAAAAAABAQEBAQEBAQEBAQEBAQEBAQEAAAAAAAAAAAAAAAAAAAEBAQEBAQEBAQEBAQ==" - }, - "palette" : { - "originalArgb8888" : [ -265674 ], - "convertedRgb565" : [ -122 ] } }, "diagnostics" : [ ] @@ -600,14 +600,14 @@ "last_modified" : 1774359772444, "fingerprint" : "eeb7cc665386299403b7be1c272375d5077f3647c587f8033aa8c9275f840562", "metadata" : { + "palette" : { + "originalArgb8888" : [ -265674 ], + "convertedRgb565" : [ -122 ] + }, "tile" : { "width" : 32, "height" : 32, "paletteIndices" : "AQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAAAAAAAAAAABAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEAAAAAAAAAAAEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQAAAAAAAAAAAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAAAAAAAAAAABAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEAAAAAAAAAAAEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQAAAAAAAAAAAQEBAQEBAQEBAQEBAAAAAAAAAAAAAAAAAAAAAAAAAAABAQEBAQEBAQEBAQEAAAAAAAAAAAAAAAAAAAAAAAAAAAEBAQEBAQEBAQEBAQAAAAAAAAAAAAAAAAAAAAAAAAAAAQEBAQEBAQEBAQEBAAAAAAAAAAAAAAAAAAAAAAAAAAABAQEBAQEBAQEBAQEAAAAAAAAAAAAAAAAAAAAAAAAAAAEBAQEBAQEBAQEBAQAAAAAAAAAAAAAAAAAAAAAAAAAAAQEBAQEBAQEBAQEBAAAAAAAAAAAAAAAAAAAAAAAAAAABAQEBAQEBAQEBAQEAAAAAAAAAAAAAAAAAAAAAAAAAAAEBAQEBAQEBAQEBAQAAAAAAAAAAAAAAAAAAAQEBAQEBAQEBAQEBAQEBAQEBAAAAAAAAAAAAAAAAAAABAQEBAQEBAQEBAQEBAQEBAQEAAAAAAAAAAAAAAAAAAAEBAQEBAQEBAQEBAQEBAQEBAQAAAAAAAAAAAAAAAAAAAQEBAQEBAQEBAQEBAAAAAAAAAAAAAAAAAAAAAAAAAAABAQEBAQEBAQEBAQEAAAAAAAAAAAAAAAAAAAAAAAAAAAEBAQEBAQEBAQEBAQAAAAAAAAAAAAAAAAAAAQEBAQEBAQEBAQEBAQEBAQEBAAAAAAAAAAAAAAAAAAABAQEBAQEBAQEBAQEBAQEBAQEAAAAAAAAAAAAAAAAAAAEBAQEBAQEBAQEBAQEBAQEBAQAAAAAAAAAAAAAAAAAAAQEBAQEBAQEBAQEBAQEBAQEBAAAAAAAAAAAAAAAAAAABAQEBAQEBAQEBAQEBAQEBAQEAAAAAAAAAAAAAAAAAAAEBAQEBAQEBAQEBAQ==" - }, - "palette" : { - "originalArgb8888" : [ -265674 ], - "convertedRgb565" : [ -122 ] } }, "diagnostics" : [ ] @@ -618,14 +618,14 @@ "last_modified" : 1774359772445, "fingerprint" : "eeb7cc665386299403b7be1c272375d5077f3647c587f8033aa8c9275f840562", "metadata" : { + "palette" : { + "originalArgb8888" : [ -265674 ], + "convertedRgb565" : [ -122 ] + }, "tile" : { "width" : 32, "height" : 32, "paletteIndices" : "AQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAAAAAAAAAAABAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEAAAAAAAAAAAEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQAAAAAAAAAAAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAAAAAAAAAAABAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEAAAAAAAAAAAEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQAAAAAAAAAAAQEBAQEBAQEBAQEBAAAAAAAAAAAAAAAAAAAAAAAAAAABAQEBAQEBAQEBAQEAAAAAAAAAAAAAAAAAAAAAAAAAAAEBAQEBAQEBAQEBAQAAAAAAAAAAAAAAAAAAAAAAAAAAAQEBAQEBAQEBAQEBAAAAAAAAAAAAAAAAAAAAAAAAAAABAQEBAQEBAQEBAQEAAAAAAAAAAAAAAAAAAAAAAAAAAAEBAQEBAQEBAQEBAQAAAAAAAAAAAAAAAAAAAAAAAAAAAQEBAQEBAQEBAQEBAAAAAAAAAAAAAAAAAAAAAAAAAAABAQEBAQEBAQEBAQEAAAAAAAAAAAAAAAAAAAAAAAAAAAEBAQEBAQEBAQEBAQAAAAAAAAAAAAAAAAAAAQEBAQEBAQEBAQEBAQEBAQEBAAAAAAAAAAAAAAAAAAABAQEBAQEBAQEBAQEBAQEBAQEAAAAAAAAAAAAAAAAAAAEBAQEBAQEBAQEBAQEBAQEBAQAAAAAAAAAAAAAAAAAAAQEBAQEBAQEBAQEBAAAAAAAAAAAAAAAAAAAAAAAAAAABAQEBAQEBAQEBAQEAAAAAAAAAAAAAAAAAAAAAAAAAAAEBAQEBAQEBAQEBAQAAAAAAAAAAAAAAAAAAAQEBAQEBAQEBAQEBAQEBAQEBAAAAAAAAAAAAAAAAAAABAQEBAQEBAQEBAQEBAQEBAQEAAAAAAAAAAAAAAAAAAAEBAQEBAQEBAQEBAQEBAQEBAQAAAAAAAAAAAAAAAAAAAQEBAQEBAQEBAQEBAQEBAQEBAAAAAAAAAAAAAAAAAAABAQEBAQEBAQEBAQEBAQEBAQEAAAAAAAAAAAAAAAAAAAEBAQEBAQEBAQEBAQ==" - }, - "palette" : { - "originalArgb8888" : [ -265674 ], - "convertedRgb565" : [ -122 ] } }, "diagnostics" : [ ] @@ -636,14 +636,14 @@ "last_modified" : 1774359772448, "fingerprint" : "eeb7cc665386299403b7be1c272375d5077f3647c587f8033aa8c9275f840562", "metadata" : { + "palette" : { + "originalArgb8888" : [ -265674 ], + "convertedRgb565" : [ -122 ] + }, "tile" : { "width" : 32, "height" : 32, "paletteIndices" : "AQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAAAAAAAAAAABAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEAAAAAAAAAAAEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQAAAAAAAAAAAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAAAAAAAAAAABAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEAAAAAAAAAAAEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQAAAAAAAAAAAQEBAQEBAQEBAQEBAAAAAAAAAAAAAAAAAAAAAAAAAAABAQEBAQEBAQEBAQEAAAAAAAAAAAAAAAAAAAAAAAAAAAEBAQEBAQEBAQEBAQAAAAAAAAAAAAAAAAAAAAAAAAAAAQEBAQEBAQEBAQEBAAAAAAAAAAAAAAAAAAAAAAAAAAABAQEBAQEBAQEBAQEAAAAAAAAAAAAAAAAAAAAAAAAAAAEBAQEBAQEBAQEBAQAAAAAAAAAAAAAAAAAAAAAAAAAAAQEBAQEBAQEBAQEBAAAAAAAAAAAAAAAAAAAAAAAAAAABAQEBAQEBAQEBAQEAAAAAAAAAAAAAAAAAAAAAAAAAAAEBAQEBAQEBAQEBAQAAAAAAAAAAAAAAAAAAAQEBAQEBAQEBAQEBAQEBAQEBAAAAAAAAAAAAAAAAAAABAQEBAQEBAQEBAQEBAQEBAQEAAAAAAAAAAAAAAAAAAAEBAQEBAQEBAQEBAQEBAQEBAQAAAAAAAAAAAAAAAAAAAQEBAQEBAQEBAQEBAAAAAAAAAAAAAAAAAAAAAAAAAAABAQEBAQEBAQEBAQEAAAAAAAAAAAAAAAAAAAAAAAAAAAEBAQEBAQEBAQEBAQAAAAAAAAAAAAAAAAAAAQEBAQEBAQEBAQEBAQEBAQEBAAAAAAAAAAAAAAAAAAABAQEBAQEBAQEBAQEBAQEBAQEAAAAAAAAAAAAAAAAAAAEBAQEBAQEBAQEBAQEBAQEBAQAAAAAAAAAAAAAAAAAAAQEBAQEBAQEBAQEBAQEBAQEBAAAAAAAAAAAAAAAAAAABAQEBAQEBAQEBAQEBAQEBAQEAAAAAAAAAAAAAAAAAAAEBAQEBAQEBAQEBAQ==" - }, - "palette" : { - "originalArgb8888" : [ -265674 ], - "convertedRgb565" : [ -122 ] } }, "diagnostics" : [ ] @@ -654,14 +654,14 @@ "last_modified" : 1774359772449, "fingerprint" : "eeb7cc665386299403b7be1c272375d5077f3647c587f8033aa8c9275f840562", "metadata" : { + "palette" : { + "originalArgb8888" : [ -265674 ], + "convertedRgb565" : [ -122 ] + }, "tile" : { "width" : 32, "height" : 32, "paletteIndices" : "AQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAAAAAAAAAAABAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEAAAAAAAAAAAEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQAAAAAAAAAAAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAAAAAAAAAAABAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEAAAAAAAAAAAEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQAAAAAAAAAAAQEBAQEBAQEBAQEBAAAAAAAAAAAAAAAAAAAAAAAAAAABAQEBAQEBAQEBAQEAAAAAAAAAAAAAAAAAAAAAAAAAAAEBAQEBAQEBAQEBAQAAAAAAAAAAAAAAAAAAAAAAAAAAAQEBAQEBAQEBAQEBAAAAAAAAAAAAAAAAAAAAAAAAAAABAQEBAQEBAQEBAQEAAAAAAAAAAAAAAAAAAAAAAAAAAAEBAQEBAQEBAQEBAQAAAAAAAAAAAAAAAAAAAAAAAAAAAQEBAQEBAQEBAQEBAAAAAAAAAAAAAAAAAAAAAAAAAAABAQEBAQEBAQEBAQEAAAAAAAAAAAAAAAAAAAAAAAAAAAEBAQEBAQEBAQEBAQAAAAAAAAAAAAAAAAAAAQEBAQEBAQEBAQEBAQEBAQEBAAAAAAAAAAAAAAAAAAABAQEBAQEBAQEBAQEBAQEBAQEAAAAAAAAAAAAAAAAAAAEBAQEBAQEBAQEBAQEBAQEBAQAAAAAAAAAAAAAAAAAAAQEBAQEBAQEBAQEBAAAAAAAAAAAAAAAAAAAAAAAAAAABAQEBAQEBAQEBAQEAAAAAAAAAAAAAAAAAAAAAAAAAAAEBAQEBAQEBAQEBAQAAAAAAAAAAAAAAAAAAAQEBAQEBAQEBAQEBAQEBAQEBAAAAAAAAAAAAAAAAAAABAQEBAQEBAQEBAQEBAQEBAQEAAAAAAAAAAAAAAAAAAAEBAQEBAQEBAQEBAQEBAQEBAQAAAAAAAAAAAAAAAAAAAQEBAQEBAQEBAQEBAQEBAQEBAAAAAAAAAAAAAAAAAAABAQEBAQEBAQEBAQEBAQEBAQEAAAAAAAAAAAAAAAAAAAEBAQEBAQEBAQEBAQ==" - }, - "palette" : { - "originalArgb8888" : [ -265674 ], - "convertedRgb565" : [ -122 ] } }, "diagnostics" : [ ] @@ -672,14 +672,14 @@ "last_modified" : 1774359772450, "fingerprint" : "eeb7cc665386299403b7be1c272375d5077f3647c587f8033aa8c9275f840562", "metadata" : { + "palette" : { + "originalArgb8888" : [ -265674 ], + "convertedRgb565" : [ -122 ] + }, "tile" : { "width" : 32, "height" : 32, "paletteIndices" : "AQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAAAAAAAAAAABAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEAAAAAAAAAAAEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQAAAAAAAAAAAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAAAAAAAAAAABAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEAAAAAAAAAAAEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQAAAAAAAAAAAQEBAQEBAQEBAQEBAAAAAAAAAAAAAAAAAAAAAAAAAAABAQEBAQEBAQEBAQEAAAAAAAAAAAAAAAAAAAAAAAAAAAEBAQEBAQEBAQEBAQAAAAAAAAAAAAAAAAAAAAAAAAAAAQEBAQEBAQEBAQEBAAAAAAAAAAAAAAAAAAAAAAAAAAABAQEBAQEBAQEBAQEAAAAAAAAAAAAAAAAAAAAAAAAAAAEBAQEBAQEBAQEBAQAAAAAAAAAAAAAAAAAAAAAAAAAAAQEBAQEBAQEBAQEBAAAAAAAAAAAAAAAAAAAAAAAAAAABAQEBAQEBAQEBAQEAAAAAAAAAAAAAAAAAAAAAAAAAAAEBAQEBAQEBAQEBAQAAAAAAAAAAAAAAAAAAAQEBAQEBAQEBAQEBAQEBAQEBAAAAAAAAAAAAAAAAAAABAQEBAQEBAQEBAQEBAQEBAQEAAAAAAAAAAAAAAAAAAAEBAQEBAQEBAQEBAQEBAQEBAQAAAAAAAAAAAAAAAAAAAQEBAQEBAQEBAQEBAAAAAAAAAAAAAAAAAAAAAAAAAAABAQEBAQEBAQEBAQEAAAAAAAAAAAAAAAAAAAAAAAAAAAEBAQEBAQEBAQEBAQAAAAAAAAAAAAAAAAAAAQEBAQEBAQEBAQEBAQEBAQEBAAAAAAAAAAAAAAAAAAABAQEBAQEBAQEBAQEBAQEBAQEAAAAAAAAAAAAAAAAAAAEBAQEBAQEBAQEBAQEBAQEBAQAAAAAAAAAAAAAAAAAAAQEBAQEBAQEBAQEBAQEBAQEBAAAAAAAAAAAAAAAAAAABAQEBAQEBAQEBAQEBAQEBAQEAAAAAAAAAAAAAAAAAAAEBAQEBAQEBAQEBAQ==" - }, - "palette" : { - "originalArgb8888" : [ -265674 ], - "convertedRgb565" : [ -122 ] } }, "diagnostics" : [ ] @@ -690,14 +690,14 @@ "last_modified" : 1774359772452, "fingerprint" : "eeb7cc665386299403b7be1c272375d5077f3647c587f8033aa8c9275f840562", "metadata" : { + "palette" : { + "originalArgb8888" : [ -265674 ], + "convertedRgb565" : [ -122 ] + }, "tile" : { "width" : 32, "height" : 32, "paletteIndices" : "AQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAAAAAAAAAAABAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEAAAAAAAAAAAEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQAAAAAAAAAAAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAAAAAAAAAAABAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEAAAAAAAAAAAEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQAAAAAAAAAAAQEBAQEBAQEBAQEBAAAAAAAAAAAAAAAAAAAAAAAAAAABAQEBAQEBAQEBAQEAAAAAAAAAAAAAAAAAAAAAAAAAAAEBAQEBAQEBAQEBAQAAAAAAAAAAAAAAAAAAAAAAAAAAAQEBAQEBAQEBAQEBAAAAAAAAAAAAAAAAAAAAAAAAAAABAQEBAQEBAQEBAQEAAAAAAAAAAAAAAAAAAAAAAAAAAAEBAQEBAQEBAQEBAQAAAAAAAAAAAAAAAAAAAAAAAAAAAQEBAQEBAQEBAQEBAAAAAAAAAAAAAAAAAAAAAAAAAAABAQEBAQEBAQEBAQEAAAAAAAAAAAAAAAAAAAAAAAAAAAEBAQEBAQEBAQEBAQAAAAAAAAAAAAAAAAAAAQEBAQEBAQEBAQEBAQEBAQEBAAAAAAAAAAAAAAAAAAABAQEBAQEBAQEBAQEBAQEBAQEAAAAAAAAAAAAAAAAAAAEBAQEBAQEBAQEBAQEBAQEBAQAAAAAAAAAAAAAAAAAAAQEBAQEBAQEBAQEBAAAAAAAAAAAAAAAAAAAAAAAAAAABAQEBAQEBAQEBAQEAAAAAAAAAAAAAAAAAAAAAAAAAAAEBAQEBAQEBAQEBAQAAAAAAAAAAAAAAAAAAAQEBAQEBAQEBAQEBAQEBAQEBAAAAAAAAAAAAAAAAAAABAQEBAQEBAQEBAQEBAQEBAQEAAAAAAAAAAAAAAAAAAAEBAQEBAQEBAQEBAQEBAQEBAQAAAAAAAAAAAAAAAAAAAQEBAQEBAQEBAQEBAQEBAQEBAAAAAAAAAAAAAAAAAAABAQEBAQEBAQEBAQEBAQEBAQEAAAAAAAAAAAAAAAAAAAEBAQEBAQEBAQEBAQ==" - }, - "palette" : { - "originalArgb8888" : [ -265674 ], - "convertedRgb565" : [ -122 ] } }, "diagnostics" : [ ] @@ -708,14 +708,14 @@ "last_modified" : 1774359772453, "fingerprint" : "eeb7cc665386299403b7be1c272375d5077f3647c587f8033aa8c9275f840562", "metadata" : { + "palette" : { + "originalArgb8888" : [ -265674 ], + "convertedRgb565" : [ -122 ] + }, "tile" : { "width" : 32, "height" : 32, "paletteIndices" : "AQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAAAAAAAAAAABAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEAAAAAAAAAAAEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQAAAAAAAAAAAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAAAAAAAAAAABAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEAAAAAAAAAAAEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQAAAAAAAAAAAQEBAQEBAQEBAQEBAAAAAAAAAAAAAAAAAAAAAAAAAAABAQEBAQEBAQEBAQEAAAAAAAAAAAAAAAAAAAAAAAAAAAEBAQEBAQEBAQEBAQAAAAAAAAAAAAAAAAAAAAAAAAAAAQEBAQEBAQEBAQEBAAAAAAAAAAAAAAAAAAAAAAAAAAABAQEBAQEBAQEBAQEAAAAAAAAAAAAAAAAAAAAAAAAAAAEBAQEBAQEBAQEBAQAAAAAAAAAAAAAAAAAAAAAAAAAAAQEBAQEBAQEBAQEBAAAAAAAAAAAAAAAAAAAAAAAAAAABAQEBAQEBAQEBAQEAAAAAAAAAAAAAAAAAAAAAAAAAAAEBAQEBAQEBAQEBAQAAAAAAAAAAAAAAAAAAAQEBAQEBAQEBAQEBAQEBAQEBAAAAAAAAAAAAAAAAAAABAQEBAQEBAQEBAQEBAQEBAQEAAAAAAAAAAAAAAAAAAAEBAQEBAQEBAQEBAQEBAQEBAQAAAAAAAAAAAAAAAAAAAQEBAQEBAQEBAQEBAAAAAAAAAAAAAAAAAAAAAAAAAAABAQEBAQEBAQEBAQEAAAAAAAAAAAAAAAAAAAAAAAAAAAEBAQEBAQEBAQEBAQAAAAAAAAAAAAAAAAAAAQEBAQEBAQEBAQEBAQEBAQEBAAAAAAAAAAAAAAAAAAABAQEBAQEBAQEBAQEBAQEBAQEAAAAAAAAAAAAAAAAAAAEBAQEBAQEBAQEBAQEBAQEBAQAAAAAAAAAAAAAAAAAAAQEBAQEBAQEBAQEBAQEBAQEBAAAAAAAAAAAAAAAAAAABAQEBAQEBAQEBAQEBAQEBAQEAAAAAAAAAAAAAAAAAAAEBAQEBAQEBAQEBAQ==" - }, - "palette" : { - "originalArgb8888" : [ -265674 ], - "convertedRgb565" : [ -122 ] } }, "diagnostics" : [ ] @@ -726,14 +726,14 @@ "last_modified" : 1774359772454, "fingerprint" : "eeb7cc665386299403b7be1c272375d5077f3647c587f8033aa8c9275f840562", "metadata" : { + "palette" : { + "originalArgb8888" : [ -265674 ], + "convertedRgb565" : [ -122 ] + }, "tile" : { "width" : 32, "height" : 32, "paletteIndices" : "AQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAAAAAAAAAAABAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEAAAAAAAAAAAEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQAAAAAAAAAAAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAAAAAAAAAAABAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEAAAAAAAAAAAEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQAAAAAAAAAAAQEBAQEBAQEBAQEBAAAAAAAAAAAAAAAAAAAAAAAAAAABAQEBAQEBAQEBAQEAAAAAAAAAAAAAAAAAAAAAAAAAAAEBAQEBAQEBAQEBAQAAAAAAAAAAAAAAAAAAAAAAAAAAAQEBAQEBAQEBAQEBAAAAAAAAAAAAAAAAAAAAAAAAAAABAQEBAQEBAQEBAQEAAAAAAAAAAAAAAAAAAAAAAAAAAAEBAQEBAQEBAQEBAQAAAAAAAAAAAAAAAAAAAAAAAAAAAQEBAQEBAQEBAQEBAAAAAAAAAAAAAAAAAAAAAAAAAAABAQEBAQEBAQEBAQEAAAAAAAAAAAAAAAAAAAAAAAAAAAEBAQEBAQEBAQEBAQAAAAAAAAAAAAAAAAAAAQEBAQEBAQEBAQEBAQEBAQEBAAAAAAAAAAAAAAAAAAABAQEBAQEBAQEBAQEBAQEBAQEAAAAAAAAAAAAAAAAAAAEBAQEBAQEBAQEBAQEBAQEBAQAAAAAAAAAAAAAAAAAAAQEBAQEBAQEBAQEBAAAAAAAAAAAAAAAAAAAAAAAAAAABAQEBAQEBAQEBAQEAAAAAAAAAAAAAAAAAAAAAAAAAAAEBAQEBAQEBAQEBAQAAAAAAAAAAAAAAAAAAAQEBAQEBAQEBAQEBAQEBAQEBAAAAAAAAAAAAAAAAAAABAQEBAQEBAQEBAQEBAQEBAQEAAAAAAAAAAAAAAAAAAAEBAQEBAQEBAQEBAQEBAQEBAQAAAAAAAAAAAAAAAAAAAQEBAQEBAQEBAQEBAQEBAQEBAAAAAAAAAAAAAAAAAAABAQEBAQEBAQEBAQEBAQEBAQEAAAAAAAAAAAAAAAAAAAEBAQEBAQEBAQEBAQ==" - }, - "palette" : { - "originalArgb8888" : [ -265674 ], - "convertedRgb565" : [ -122 ] } }, "diagnostics" : [ ] @@ -744,14 +744,14 @@ "last_modified" : 1774359772455, "fingerprint" : "eeb7cc665386299403b7be1c272375d5077f3647c587f8033aa8c9275f840562", "metadata" : { + "palette" : { + "originalArgb8888" : [ -265674 ], + "convertedRgb565" : [ -122 ] + }, "tile" : { "width" : 32, "height" : 32, "paletteIndices" : "AQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAAAAAAAAAAABAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEAAAAAAAAAAAEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQAAAAAAAAAAAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAAAAAAAAAAABAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEAAAAAAAAAAAEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQAAAAAAAAAAAQEBAQEBAQEBAQEBAAAAAAAAAAAAAAAAAAAAAAAAAAABAQEBAQEBAQEBAQEAAAAAAAAAAAAAAAAAAAAAAAAAAAEBAQEBAQEBAQEBAQAAAAAAAAAAAAAAAAAAAAAAAAAAAQEBAQEBAQEBAQEBAAAAAAAAAAAAAAAAAAAAAAAAAAABAQEBAQEBAQEBAQEAAAAAAAAAAAAAAAAAAAAAAAAAAAEBAQEBAQEBAQEBAQAAAAAAAAAAAAAAAAAAAAAAAAAAAQEBAQEBAQEBAQEBAAAAAAAAAAAAAAAAAAAAAAAAAAABAQEBAQEBAQEBAQEAAAAAAAAAAAAAAAAAAAAAAAAAAAEBAQEBAQEBAQEBAQAAAAAAAAAAAAAAAAAAAQEBAQEBAQEBAQEBAQEBAQEBAAAAAAAAAAAAAAAAAAABAQEBAQEBAQEBAQEBAQEBAQEAAAAAAAAAAAAAAAAAAAEBAQEBAQEBAQEBAQEBAQEBAQAAAAAAAAAAAAAAAAAAAQEBAQEBAQEBAQEBAAAAAAAAAAAAAAAAAAAAAAAAAAABAQEBAQEBAQEBAQEAAAAAAAAAAAAAAAAAAAAAAAAAAAEBAQEBAQEBAQEBAQAAAAAAAAAAAAAAAAAAAQEBAQEBAQEBAQEBAQEBAQEBAAAAAAAAAAAAAAAAAAABAQEBAQEBAQEBAQEBAQEBAQEAAAAAAAAAAAAAAAAAAAEBAQEBAQEBAQEBAQEBAQEBAQAAAAAAAAAAAAAAAAAAAQEBAQEBAQEBAQEBAQEBAQEBAAAAAAAAAAAAAAAAAAABAQEBAQEBAQEBAQEBAQEBAQEAAAAAAAAAAAAAAAAAAAEBAQEBAQEBAQEBAQ==" - }, - "palette" : { - "originalArgb8888" : [ -265674 ], - "convertedRgb565" : [ -122 ] } }, "diagnostics" : [ ] @@ -762,14 +762,14 @@ "last_modified" : 1774359772456, "fingerprint" : "eeb7cc665386299403b7be1c272375d5077f3647c587f8033aa8c9275f840562", "metadata" : { + "palette" : { + "originalArgb8888" : [ -265674 ], + "convertedRgb565" : [ -122 ] + }, "tile" : { "width" : 32, "height" : 32, "paletteIndices" : "AQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAAAAAAAAAAABAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEAAAAAAAAAAAEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQAAAAAAAAAAAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAAAAAAAAAAABAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEAAAAAAAAAAAEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQAAAAAAAAAAAQEBAQEBAQEBAQEBAAAAAAAAAAAAAAAAAAAAAAAAAAABAQEBAQEBAQEBAQEAAAAAAAAAAAAAAAAAAAAAAAAAAAEBAQEBAQEBAQEBAQAAAAAAAAAAAAAAAAAAAAAAAAAAAQEBAQEBAQEBAQEBAAAAAAAAAAAAAAAAAAAAAAAAAAABAQEBAQEBAQEBAQEAAAAAAAAAAAAAAAAAAAAAAAAAAAEBAQEBAQEBAQEBAQAAAAAAAAAAAAAAAAAAAAAAAAAAAQEBAQEBAQEBAQEBAAAAAAAAAAAAAAAAAAAAAAAAAAABAQEBAQEBAQEBAQEAAAAAAAAAAAAAAAAAAAAAAAAAAAEBAQEBAQEBAQEBAQAAAAAAAAAAAAAAAAAAAQEBAQEBAQEBAQEBAQEBAQEBAAAAAAAAAAAAAAAAAAABAQEBAQEBAQEBAQEBAQEBAQEAAAAAAAAAAAAAAAAAAAEBAQEBAQEBAQEBAQEBAQEBAQAAAAAAAAAAAAAAAAAAAQEBAQEBAQEBAQEBAAAAAAAAAAAAAAAAAAAAAAAAAAABAQEBAQEBAQEBAQEAAAAAAAAAAAAAAAAAAAAAAAAAAAEBAQEBAQEBAQEBAQAAAAAAAAAAAAAAAAAAAQEBAQEBAQEBAQEBAQEBAQEBAAAAAAAAAAAAAAAAAAABAQEBAQEBAQEBAQEBAQEBAQEAAAAAAAAAAAAAAAAAAAEBAQEBAQEBAQEBAQEBAQEBAQAAAAAAAAAAAAAAAAAAAQEBAQEBAQEBAQEBAQEBAQEBAAAAAAAAAAAAAAAAAAABAQEBAQEBAQEBAQEBAQEBAQEAAAAAAAAAAAAAAAAAAAEBAQEBAQEBAQEBAQ==" - }, - "palette" : { - "originalArgb8888" : [ -265674 ], - "convertedRgb565" : [ -122 ] } }, "diagnostics" : [ ] @@ -780,14 +780,14 @@ "last_modified" : 1774359772458, "fingerprint" : "eeb7cc665386299403b7be1c272375d5077f3647c587f8033aa8c9275f840562", "metadata" : { + "palette" : { + "originalArgb8888" : [ -265674 ], + "convertedRgb565" : [ -122 ] + }, "tile" : { "width" : 32, "height" : 32, "paletteIndices" : "AQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAAAAAAAAAAABAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEAAAAAAAAAAAEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQAAAAAAAAAAAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAAAAAAAAAAABAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEAAAAAAAAAAAEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQAAAAAAAAAAAQEBAQEBAQEBAQEBAAAAAAAAAAAAAAAAAAAAAAAAAAABAQEBAQEBAQEBAQEAAAAAAAAAAAAAAAAAAAAAAAAAAAEBAQEBAQEBAQEBAQAAAAAAAAAAAAAAAAAAAAAAAAAAAQEBAQEBAQEBAQEBAAAAAAAAAAAAAAAAAAAAAAAAAAABAQEBAQEBAQEBAQEAAAAAAAAAAAAAAAAAAAAAAAAAAAEBAQEBAQEBAQEBAQAAAAAAAAAAAAAAAAAAAAAAAAAAAQEBAQEBAQEBAQEBAAAAAAAAAAAAAAAAAAAAAAAAAAABAQEBAQEBAQEBAQEAAAAAAAAAAAAAAAAAAAAAAAAAAAEBAQEBAQEBAQEBAQAAAAAAAAAAAAAAAAAAAQEBAQEBAQEBAQEBAQEBAQEBAAAAAAAAAAAAAAAAAAABAQEBAQEBAQEBAQEBAQEBAQEAAAAAAAAAAAAAAAAAAAEBAQEBAQEBAQEBAQEBAQEBAQAAAAAAAAAAAAAAAAAAAQEBAQEBAQEBAQEBAAAAAAAAAAAAAAAAAAAAAAAAAAABAQEBAQEBAQEBAQEAAAAAAAAAAAAAAAAAAAAAAAAAAAEBAQEBAQEBAQEBAQAAAAAAAAAAAAAAAAAAAQEBAQEBAQEBAQEBAQEBAQEBAAAAAAAAAAAAAAAAAAABAQEBAQEBAQEBAQEBAQEBAQEAAAAAAAAAAAAAAAAAAAEBAQEBAQEBAQEBAQEBAQEBAQAAAAAAAAAAAAAAAAAAAQEBAQEBAQEBAQEBAQEBAQEBAAAAAAAAAAAAAAAAAAABAQEBAQEBAQEBAQEBAQEBAQEAAAAAAAAAAAAAAAAAAAEBAQEBAQEBAQEBAQ==" - }, - "palette" : { - "originalArgb8888" : [ -265674 ], - "convertedRgb565" : [ -122 ] } }, "diagnostics" : [ ] @@ -798,14 +798,14 @@ "last_modified" : 1774359772459, "fingerprint" : "eeb7cc665386299403b7be1c272375d5077f3647c587f8033aa8c9275f840562", "metadata" : { + "palette" : { + "originalArgb8888" : [ -265674 ], + "convertedRgb565" : [ -122 ] + }, "tile" : { "width" : 32, "height" : 32, "paletteIndices" : "AQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAAAAAAAAAAABAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEAAAAAAAAAAAEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQAAAAAAAAAAAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAAAAAAAAAAABAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEAAAAAAAAAAAEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQAAAAAAAAAAAQEBAQEBAQEBAQEBAAAAAAAAAAAAAAAAAAAAAAAAAAABAQEBAQEBAQEBAQEAAAAAAAAAAAAAAAAAAAAAAAAAAAEBAQEBAQEBAQEBAQAAAAAAAAAAAAAAAAAAAAAAAAAAAQEBAQEBAQEBAQEBAAAAAAAAAAAAAAAAAAAAAAAAAAABAQEBAQEBAQEBAQEAAAAAAAAAAAAAAAAAAAAAAAAAAAEBAQEBAQEBAQEBAQAAAAAAAAAAAAAAAAAAAAAAAAAAAQEBAQEBAQEBAQEBAAAAAAAAAAAAAAAAAAAAAAAAAAABAQEBAQEBAQEBAQEAAAAAAAAAAAAAAAAAAAAAAAAAAAEBAQEBAQEBAQEBAQAAAAAAAAAAAAAAAAAAAQEBAQEBAQEBAQEBAQEBAQEBAAAAAAAAAAAAAAAAAAABAQEBAQEBAQEBAQEBAQEBAQEAAAAAAAAAAAAAAAAAAAEBAQEBAQEBAQEBAQEBAQEBAQAAAAAAAAAAAAAAAAAAAQEBAQEBAQEBAQEBAAAAAAAAAAAAAAAAAAAAAAAAAAABAQEBAQEBAQEBAQEAAAAAAAAAAAAAAAAAAAAAAAAAAAEBAQEBAQEBAQEBAQAAAAAAAAAAAAAAAAAAAQEBAQEBAQEBAQEBAQEBAQEBAAAAAAAAAAAAAAAAAAABAQEBAQEBAQEBAQEBAQEBAQEAAAAAAAAAAAAAAAAAAAEBAQEBAQEBAQEBAQEBAQEBAQAAAAAAAAAAAAAAAAAAAQEBAQEBAQEBAQEBAQEBAQEBAAAAAAAAAAAAAAAAAAABAQEBAQEBAQEBAQEBAQEBAQEAAAAAAAAAAAAAAAAAAAEBAQEBAQEBAQEBAQ==" - }, - "palette" : { - "originalArgb8888" : [ -265674 ], - "convertedRgb565" : [ -122 ] } }, "diagnostics" : [ ] @@ -816,14 +816,14 @@ "last_modified" : 1774359772460, "fingerprint" : "eeb7cc665386299403b7be1c272375d5077f3647c587f8033aa8c9275f840562", "metadata" : { + "palette" : { + "originalArgb8888" : [ -265674 ], + "convertedRgb565" : [ -122 ] + }, "tile" : { "width" : 32, "height" : 32, "paletteIndices" : "AQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAAAAAAAAAAABAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEAAAAAAAAAAAEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQAAAAAAAAAAAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAAAAAAAAAAABAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEAAAAAAAAAAAEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQAAAAAAAAAAAQEBAQEBAQEBAQEBAAAAAAAAAAAAAAAAAAAAAAAAAAABAQEBAQEBAQEBAQEAAAAAAAAAAAAAAAAAAAAAAAAAAAEBAQEBAQEBAQEBAQAAAAAAAAAAAAAAAAAAAAAAAAAAAQEBAQEBAQEBAQEBAAAAAAAAAAAAAAAAAAAAAAAAAAABAQEBAQEBAQEBAQEAAAAAAAAAAAAAAAAAAAAAAAAAAAEBAQEBAQEBAQEBAQAAAAAAAAAAAAAAAAAAAAAAAAAAAQEBAQEBAQEBAQEBAAAAAAAAAAAAAAAAAAAAAAAAAAABAQEBAQEBAQEBAQEAAAAAAAAAAAAAAAAAAAAAAAAAAAEBAQEBAQEBAQEBAQAAAAAAAAAAAAAAAAAAAQEBAQEBAQEBAQEBAQEBAQEBAAAAAAAAAAAAAAAAAAABAQEBAQEBAQEBAQEBAQEBAQEAAAAAAAAAAAAAAAAAAAEBAQEBAQEBAQEBAQEBAQEBAQAAAAAAAAAAAAAAAAAAAQEBAQEBAQEBAQEBAAAAAAAAAAAAAAAAAAAAAAAAAAABAQEBAQEBAQEBAQEAAAAAAAAAAAAAAAAAAAAAAAAAAAEBAQEBAQEBAQEBAQAAAAAAAAAAAAAAAAAAAQEBAQEBAQEBAQEBAQEBAQEBAAAAAAAAAAAAAAAAAAABAQEBAQEBAQEBAQEBAQEBAQEAAAAAAAAAAAAAAAAAAAEBAQEBAQEBAQEBAQEBAQEBAQAAAAAAAAAAAAAAAAAAAQEBAQEBAQEBAQEBAQEBAQEBAAAAAAAAAAAAAAAAAAABAQEBAQEBAQEBAQEBAQEBAQEAAAAAAAAAAAAAAAAAAAEBAQEBAQEBAQEBAQ==" - }, - "palette" : { - "originalArgb8888" : [ -265674 ], - "convertedRgb565" : [ -122 ] } }, "diagnostics" : [ ] @@ -834,14 +834,14 @@ "last_modified" : 1774359772461, "fingerprint" : "eeb7cc665386299403b7be1c272375d5077f3647c587f8033aa8c9275f840562", "metadata" : { + "palette" : { + "originalArgb8888" : [ -265674 ], + "convertedRgb565" : [ -122 ] + }, "tile" : { "width" : 32, "height" : 32, "paletteIndices" : "AQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAAAAAAAAAAABAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEAAAAAAAAAAAEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQAAAAAAAAAAAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAAAAAAAAAAABAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEAAAAAAAAAAAEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQAAAAAAAAAAAQEBAQEBAQEBAQEBAAAAAAAAAAAAAAAAAAAAAAAAAAABAQEBAQEBAQEBAQEAAAAAAAAAAAAAAAAAAAAAAAAAAAEBAQEBAQEBAQEBAQAAAAAAAAAAAAAAAAAAAAAAAAAAAQEBAQEBAQEBAQEBAAAAAAAAAAAAAAAAAAAAAAAAAAABAQEBAQEBAQEBAQEAAAAAAAAAAAAAAAAAAAAAAAAAAAEBAQEBAQEBAQEBAQAAAAAAAAAAAAAAAAAAAAAAAAAAAQEBAQEBAQEBAQEBAAAAAAAAAAAAAAAAAAAAAAAAAAABAQEBAQEBAQEBAQEAAAAAAAAAAAAAAAAAAAAAAAAAAAEBAQEBAQEBAQEBAQAAAAAAAAAAAAAAAAAAAQEBAQEBAQEBAQEBAQEBAQEBAAAAAAAAAAAAAAAAAAABAQEBAQEBAQEBAQEBAQEBAQEAAAAAAAAAAAAAAAAAAAEBAQEBAQEBAQEBAQEBAQEBAQAAAAAAAAAAAAAAAAAAAQEBAQEBAQEBAQEBAAAAAAAAAAAAAAAAAAAAAAAAAAABAQEBAQEBAQEBAQEAAAAAAAAAAAAAAAAAAAAAAAAAAAEBAQEBAQEBAQEBAQAAAAAAAAAAAAAAAAAAAQEBAQEBAQEBAQEBAQEBAQEBAAAAAAAAAAAAAAAAAAABAQEBAQEBAQEBAQEBAQEBAQEAAAAAAAAAAAAAAAAAAAEBAQEBAQEBAQEBAQEBAQEBAQAAAAAAAAAAAAAAAAAAAQEBAQEBAQEBAQEBAQEBAQEBAAAAAAAAAAAAAAAAAAABAQEBAQEBAQEBAQEBAQEBAQEAAAAAAAAAAAAAAAAAAAEBAQEBAQEBAQEBAQ==" - }, - "palette" : { - "originalArgb8888" : [ -265674 ], - "convertedRgb565" : [ -122 ] } }, "diagnostics" : [ ] @@ -852,14 +852,14 @@ "last_modified" : 1774359772463, "fingerprint" : "eeb7cc665386299403b7be1c272375d5077f3647c587f8033aa8c9275f840562", "metadata" : { + "palette" : { + "originalArgb8888" : [ -265674 ], + "convertedRgb565" : [ -122 ] + }, "tile" : { "width" : 32, "height" : 32, "paletteIndices" : "AQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAAAAAAAAAAABAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEAAAAAAAAAAAEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQAAAAAAAAAAAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAAAAAAAAAAABAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEAAAAAAAAAAAEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQAAAAAAAAAAAQEBAQEBAQEBAQEBAAAAAAAAAAAAAAAAAAAAAAAAAAABAQEBAQEBAQEBAQEAAAAAAAAAAAAAAAAAAAAAAAAAAAEBAQEBAQEBAQEBAQAAAAAAAAAAAAAAAAAAAAAAAAAAAQEBAQEBAQEBAQEBAAAAAAAAAAAAAAAAAAAAAAAAAAABAQEBAQEBAQEBAQEAAAAAAAAAAAAAAAAAAAAAAAAAAAEBAQEBAQEBAQEBAQAAAAAAAAAAAAAAAAAAAAAAAAAAAQEBAQEBAQEBAQEBAAAAAAAAAAAAAAAAAAAAAAAAAAABAQEBAQEBAQEBAQEAAAAAAAAAAAAAAAAAAAAAAAAAAAEBAQEBAQEBAQEBAQAAAAAAAAAAAAAAAAAAAQEBAQEBAQEBAQEBAQEBAQEBAAAAAAAAAAAAAAAAAAABAQEBAQEBAQEBAQEBAQEBAQEAAAAAAAAAAAAAAAAAAAEBAQEBAQEBAQEBAQEBAQEBAQAAAAAAAAAAAAAAAAAAAQEBAQEBAQEBAQEBAAAAAAAAAAAAAAAAAAAAAAAAAAABAQEBAQEBAQEBAQEAAAAAAAAAAAAAAAAAAAAAAAAAAAEBAQEBAQEBAQEBAQAAAAAAAAAAAAAAAAAAAQEBAQEBAQEBAQEBAQEBAQEBAAAAAAAAAAAAAAAAAAABAQEBAQEBAQEBAQEBAQEBAQEAAAAAAAAAAAAAAAAAAAEBAQEBAQEBAQEBAQEBAQEBAQAAAAAAAAAAAAAAAAAAAQEBAQEBAQEBAQEBAQEBAQEBAAAAAAAAAAAAAAAAAAABAQEBAQEBAQEBAQEBAQEBAQEAAAAAAAAAAAAAAAAAAAEBAQEBAQEBAQEBAQ==" - }, - "palette" : { - "originalArgb8888" : [ -265674 ], - "convertedRgb565" : [ -122 ] } }, "diagnostics" : [ ] @@ -870,14 +870,14 @@ "last_modified" : 1774359772464, "fingerprint" : "eeb7cc665386299403b7be1c272375d5077f3647c587f8033aa8c9275f840562", "metadata" : { + "palette" : { + "originalArgb8888" : [ -265674 ], + "convertedRgb565" : [ -122 ] + }, "tile" : { "width" : 32, "height" : 32, "paletteIndices" : "AQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAAAAAAAAAAABAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEAAAAAAAAAAAEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQAAAAAAAAAAAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAAAAAAAAAAABAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEAAAAAAAAAAAEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQAAAAAAAAAAAQEBAQEBAQEBAQEBAAAAAAAAAAAAAAAAAAAAAAAAAAABAQEBAQEBAQEBAQEAAAAAAAAAAAAAAAAAAAAAAAAAAAEBAQEBAQEBAQEBAQAAAAAAAAAAAAAAAAAAAAAAAAAAAQEBAQEBAQEBAQEBAAAAAAAAAAAAAAAAAAAAAAAAAAABAQEBAQEBAQEBAQEAAAAAAAAAAAAAAAAAAAAAAAAAAAEBAQEBAQEBAQEBAQAAAAAAAAAAAAAAAAAAAAAAAAAAAQEBAQEBAQEBAQEBAAAAAAAAAAAAAAAAAAAAAAAAAAABAQEBAQEBAQEBAQEAAAAAAAAAAAAAAAAAAAAAAAAAAAEBAQEBAQEBAQEBAQAAAAAAAAAAAAAAAAAAAQEBAQEBAQEBAQEBAQEBAQEBAAAAAAAAAAAAAAAAAAABAQEBAQEBAQEBAQEBAQEBAQEAAAAAAAAAAAAAAAAAAAEBAQEBAQEBAQEBAQEBAQEBAQAAAAAAAAAAAAAAAAAAAQEBAQEBAQEBAQEBAAAAAAAAAAAAAAAAAAAAAAAAAAABAQEBAQEBAQEBAQEAAAAAAAAAAAAAAAAAAAAAAAAAAAEBAQEBAQEBAQEBAQAAAAAAAAAAAAAAAAAAAQEBAQEBAQEBAQEBAQEBAQEBAAAAAAAAAAAAAAAAAAABAQEBAQEBAQEBAQEBAQEBAQEAAAAAAAAAAAAAAAAAAAEBAQEBAQEBAQEBAQEBAQEBAQAAAAAAAAAAAAAAAAAAAQEBAQEBAQEBAQEBAQEBAQEBAAAAAAAAAAAAAAAAAAABAQEBAQEBAQEBAQEBAQEBAQEAAAAAAAAAAAAAAAAAAAEBAQEBAQEBAQEBAQ==" - }, - "palette" : { - "originalArgb8888" : [ -265674 ], - "convertedRgb565" : [ -122 ] } }, "diagnostics" : [ ] @@ -888,14 +888,14 @@ "last_modified" : 1774359772465, "fingerprint" : "eeb7cc665386299403b7be1c272375d5077f3647c587f8033aa8c9275f840562", "metadata" : { + "palette" : { + "originalArgb8888" : [ -265674 ], + "convertedRgb565" : [ -122 ] + }, "tile" : { "width" : 32, "height" : 32, "paletteIndices" : "AQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAAAAAAAAAAABAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEAAAAAAAAAAAEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQAAAAAAAAAAAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAAAAAAAAAAABAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEAAAAAAAAAAAEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQAAAAAAAAAAAQEBAQEBAQEBAQEBAAAAAAAAAAAAAAAAAAAAAAAAAAABAQEBAQEBAQEBAQEAAAAAAAAAAAAAAAAAAAAAAAAAAAEBAQEBAQEBAQEBAQAAAAAAAAAAAAAAAAAAAAAAAAAAAQEBAQEBAQEBAQEBAAAAAAAAAAAAAAAAAAAAAAAAAAABAQEBAQEBAQEBAQEAAAAAAAAAAAAAAAAAAAAAAAAAAAEBAQEBAQEBAQEBAQAAAAAAAAAAAAAAAAAAAAAAAAAAAQEBAQEBAQEBAQEBAAAAAAAAAAAAAAAAAAAAAAAAAAABAQEBAQEBAQEBAQEAAAAAAAAAAAAAAAAAAAAAAAAAAAEBAQEBAQEBAQEBAQAAAAAAAAAAAAAAAAAAAQEBAQEBAQEBAQEBAQEBAQEBAAAAAAAAAAAAAAAAAAABAQEBAQEBAQEBAQEBAQEBAQEAAAAAAAAAAAAAAAAAAAEBAQEBAQEBAQEBAQEBAQEBAQAAAAAAAAAAAAAAAAAAAQEBAQEBAQEBAQEBAAAAAAAAAAAAAAAAAAAAAAAAAAABAQEBAQEBAQEBAQEAAAAAAAAAAAAAAAAAAAAAAAAAAAEBAQEBAQEBAQEBAQAAAAAAAAAAAAAAAAAAAQEBAQEBAQEBAQEBAQEBAQEBAAAAAAAAAAAAAAAAAAABAQEBAQEBAQEBAQEBAQEBAQEAAAAAAAAAAAAAAAAAAAEBAQEBAQEBAQEBAQEBAQEBAQAAAAAAAAAAAAAAAAAAAQEBAQEBAQEBAQEBAQEBAQEBAAAAAAAAAAAAAAAAAAABAQEBAQEBAQEBAQEBAQEBAQEAAAAAAAAAAAAAAAAAAAEBAQEBAQEBAQEBAQ==" - }, - "palette" : { - "originalArgb8888" : [ -265674 ], - "convertedRgb565" : [ -122 ] } }, "diagnostics" : [ ] @@ -906,14 +906,14 @@ "last_modified" : 1774359772467, "fingerprint" : "eeb7cc665386299403b7be1c272375d5077f3647c587f8033aa8c9275f840562", "metadata" : { + "palette" : { + "originalArgb8888" : [ -265674 ], + "convertedRgb565" : [ -122 ] + }, "tile" : { "width" : 32, "height" : 32, "paletteIndices" : "AQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAAAAAAAAAAABAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEAAAAAAAAAAAEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQAAAAAAAAAAAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAAAAAAAAAAABAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEAAAAAAAAAAAEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQAAAAAAAAAAAQEBAQEBAQEBAQEBAAAAAAAAAAAAAAAAAAAAAAAAAAABAQEBAQEBAQEBAQEAAAAAAAAAAAAAAAAAAAAAAAAAAAEBAQEBAQEBAQEBAQAAAAAAAAAAAAAAAAAAAAAAAAAAAQEBAQEBAQEBAQEBAAAAAAAAAAAAAAAAAAAAAAAAAAABAQEBAQEBAQEBAQEAAAAAAAAAAAAAAAAAAAAAAAAAAAEBAQEBAQEBAQEBAQAAAAAAAAAAAAAAAAAAAAAAAAAAAQEBAQEBAQEBAQEBAAAAAAAAAAAAAAAAAAAAAAAAAAABAQEBAQEBAQEBAQEAAAAAAAAAAAAAAAAAAAAAAAAAAAEBAQEBAQEBAQEBAQAAAAAAAAAAAAAAAAAAAQEBAQEBAQEBAQEBAQEBAQEBAAAAAAAAAAAAAAAAAAABAQEBAQEBAQEBAQEBAQEBAQEAAAAAAAAAAAAAAAAAAAEBAQEBAQEBAQEBAQEBAQEBAQAAAAAAAAAAAAAAAAAAAQEBAQEBAQEBAQEBAAAAAAAAAAAAAAAAAAAAAAAAAAABAQEBAQEBAQEBAQEAAAAAAAAAAAAAAAAAAAAAAAAAAAEBAQEBAQEBAQEBAQAAAAAAAAAAAAAAAAAAAQEBAQEBAQEBAQEBAQEBAQEBAAAAAAAAAAAAAAAAAAABAQEBAQEBAQEBAQEBAQEBAQEAAAAAAAAAAAAAAAAAAAEBAQEBAQEBAQEBAQEBAQEBAQAAAAAAAAAAAAAAAAAAAQEBAQEBAQEBAQEBAQEBAQEBAAAAAAAAAAAAAAAAAAABAQEBAQEBAQEBAQEBAQEBAQEAAAAAAAAAAAAAAAAAAAEBAQEBAQEBAQEBAQ==" - }, - "palette" : { - "originalArgb8888" : [ -265674 ], - "convertedRgb565" : [ -122 ] } }, "diagnostics" : [ ] @@ -924,14 +924,14 @@ "last_modified" : 1774359772468, "fingerprint" : "eeb7cc665386299403b7be1c272375d5077f3647c587f8033aa8c9275f840562", "metadata" : { + "palette" : { + "originalArgb8888" : [ -265674 ], + "convertedRgb565" : [ -122 ] + }, "tile" : { "width" : 32, "height" : 32, "paletteIndices" : "AQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAAAAAAAAAAABAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEAAAAAAAAAAAEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQAAAAAAAAAAAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAAAAAAAAAAABAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEAAAAAAAAAAAEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQAAAAAAAAAAAQEBAQEBAQEBAQEBAAAAAAAAAAAAAAAAAAAAAAAAAAABAQEBAQEBAQEBAQEAAAAAAAAAAAAAAAAAAAAAAAAAAAEBAQEBAQEBAQEBAQAAAAAAAAAAAAAAAAAAAAAAAAAAAQEBAQEBAQEBAQEBAAAAAAAAAAAAAAAAAAAAAAAAAAABAQEBAQEBAQEBAQEAAAAAAAAAAAAAAAAAAAAAAAAAAAEBAQEBAQEBAQEBAQAAAAAAAAAAAAAAAAAAAAAAAAAAAQEBAQEBAQEBAQEBAAAAAAAAAAAAAAAAAAAAAAAAAAABAQEBAQEBAQEBAQEAAAAAAAAAAAAAAAAAAAAAAAAAAAEBAQEBAQEBAQEBAQAAAAAAAAAAAAAAAAAAAQEBAQEBAQEBAQEBAQEBAQEBAAAAAAAAAAAAAAAAAAABAQEBAQEBAQEBAQEBAQEBAQEAAAAAAAAAAAAAAAAAAAEBAQEBAQEBAQEBAQEBAQEBAQAAAAAAAAAAAAAAAAAAAQEBAQEBAQEBAQEBAAAAAAAAAAAAAAAAAAAAAAAAAAABAQEBAQEBAQEBAQEAAAAAAAAAAAAAAAAAAAAAAAAAAAEBAQEBAQEBAQEBAQAAAAAAAAAAAAAAAAAAAQEBAQEBAQEBAQEBAQEBAQEBAAAAAAAAAAAAAAAAAAABAQEBAQEBAQEBAQEBAQEBAQEAAAAAAAAAAAAAAAAAAAEBAQEBAQEBAQEBAQEBAQEBAQAAAAAAAAAAAAAAAAAAAQEBAQEBAQEBAQEBAQEBAQEBAAAAAAAAAAAAAAAAAAABAQEBAQEBAQEBAQEBAQEBAQEAAAAAAAAAAAAAAAAAAAEBAQEBAQEBAQEBAQ==" - }, - "palette" : { - "originalArgb8888" : [ -265674 ], - "convertedRgb565" : [ -122 ] } }, "diagnostics" : [ ] @@ -942,14 +942,14 @@ "last_modified" : 1774359772470, "fingerprint" : "eeb7cc665386299403b7be1c272375d5077f3647c587f8033aa8c9275f840562", "metadata" : { + "palette" : { + "originalArgb8888" : [ -265674 ], + "convertedRgb565" : [ -122 ] + }, "tile" : { "width" : 32, "height" : 32, "paletteIndices" : "AQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAAAAAAAAAAABAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEAAAAAAAAAAAEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQAAAAAAAAAAAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAAAAAAAAAAABAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEAAAAAAAAAAAEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQAAAAAAAAAAAQEBAQEBAQEBAQEBAAAAAAAAAAAAAAAAAAAAAAAAAAABAQEBAQEBAQEBAQEAAAAAAAAAAAAAAAAAAAAAAAAAAAEBAQEBAQEBAQEBAQAAAAAAAAAAAAAAAAAAAAAAAAAAAQEBAQEBAQEBAQEBAAAAAAAAAAAAAAAAAAAAAAAAAAABAQEBAQEBAQEBAQEAAAAAAAAAAAAAAAAAAAAAAAAAAAEBAQEBAQEBAQEBAQAAAAAAAAAAAAAAAAAAAAAAAAAAAQEBAQEBAQEBAQEBAAAAAAAAAAAAAAAAAAAAAAAAAAABAQEBAQEBAQEBAQEAAAAAAAAAAAAAAAAAAAAAAAAAAAEBAQEBAQEBAQEBAQAAAAAAAAAAAAAAAAAAAQEBAQEBAQEBAQEBAQEBAQEBAAAAAAAAAAAAAAAAAAABAQEBAQEBAQEBAQEBAQEBAQEAAAAAAAAAAAAAAAAAAAEBAQEBAQEBAQEBAQEBAQEBAQAAAAAAAAAAAAAAAAAAAQEBAQEBAQEBAQEBAAAAAAAAAAAAAAAAAAAAAAAAAAABAQEBAQEBAQEBAQEAAAAAAAAAAAAAAAAAAAAAAAAAAAEBAQEBAQEBAQEBAQAAAAAAAAAAAAAAAAAAAQEBAQEBAQEBAQEBAQEBAQEBAAAAAAAAAAAAAAAAAAABAQEBAQEBAQEBAQEBAQEBAQEAAAAAAAAAAAAAAAAAAAEBAQEBAQEBAQEBAQEBAQEBAQAAAAAAAAAAAAAAAAAAAQEBAQEBAQEBAQEBAQEBAQEBAAAAAAAAAAAAAAAAAAABAQEBAQEBAQEBAQEBAQEBAQEAAAAAAAAAAAAAAAAAAAEBAQEBAQEBAQEBAQ==" - }, - "palette" : { - "originalArgb8888" : [ -265674 ], - "convertedRgb565" : [ -122 ] } }, "diagnostics" : [ ] @@ -960,14 +960,14 @@ "last_modified" : 1774359772474, "fingerprint" : "eeb7cc665386299403b7be1c272375d5077f3647c587f8033aa8c9275f840562", "metadata" : { + "palette" : { + "originalArgb8888" : [ -265674 ], + "convertedRgb565" : [ -122 ] + }, "tile" : { "width" : 32, "height" : 32, "paletteIndices" : "AQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAAAAAAAAAAABAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEAAAAAAAAAAAEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQAAAAAAAAAAAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAAAAAAAAAAABAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEAAAAAAAAAAAEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQAAAAAAAAAAAQEBAQEBAQEBAQEBAAAAAAAAAAAAAAAAAAAAAAAAAAABAQEBAQEBAQEBAQEAAAAAAAAAAAAAAAAAAAAAAAAAAAEBAQEBAQEBAQEBAQAAAAAAAAAAAAAAAAAAAAAAAAAAAQEBAQEBAQEBAQEBAAAAAAAAAAAAAAAAAAAAAAAAAAABAQEBAQEBAQEBAQEAAAAAAAAAAAAAAAAAAAAAAAAAAAEBAQEBAQEBAQEBAQAAAAAAAAAAAAAAAAAAAAAAAAAAAQEBAQEBAQEBAQEBAAAAAAAAAAAAAAAAAAAAAAAAAAABAQEBAQEBAQEBAQEAAAAAAAAAAAAAAAAAAAAAAAAAAAEBAQEBAQEBAQEBAQAAAAAAAAAAAAAAAAAAAQEBAQEBAQEBAQEBAQEBAQEBAAAAAAAAAAAAAAAAAAABAQEBAQEBAQEBAQEBAQEBAQEAAAAAAAAAAAAAAAAAAAEBAQEBAQEBAQEBAQEBAQEBAQAAAAAAAAAAAAAAAAAAAQEBAQEBAQEBAQEBAAAAAAAAAAAAAAAAAAAAAAAAAAABAQEBAQEBAQEBAQEAAAAAAAAAAAAAAAAAAAAAAAAAAAEBAQEBAQEBAQEBAQAAAAAAAAAAAAAAAAAAAQEBAQEBAQEBAQEBAQEBAQEBAAAAAAAAAAAAAAAAAAABAQEBAQEBAQEBAQEBAQEBAQEAAAAAAAAAAAAAAAAAAAEBAQEBAQEBAQEBAQEBAQEBAQAAAAAAAAAAAAAAAAAAAQEBAQEBAQEBAQEBAQEBAQEBAAAAAAAAAAAAAAAAAAABAQEBAQEBAQEBAQEBAQEBAQEAAAAAAAAAAAAAAAAAAAEBAQEBAQEBAQEBAQ==" - }, - "palette" : { - "originalArgb8888" : [ -265674 ], - "convertedRgb565" : [ -122 ] } }, "diagnostics" : [ ] @@ -978,14 +978,14 @@ "last_modified" : 1774359772476, "fingerprint" : "eeb7cc665386299403b7be1c272375d5077f3647c587f8033aa8c9275f840562", "metadata" : { + "palette" : { + "originalArgb8888" : [ -265674 ], + "convertedRgb565" : [ -122 ] + }, "tile" : { "width" : 32, "height" : 32, "paletteIndices" : "AQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAAAAAAAAAAABAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEAAAAAAAAAAAEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQAAAAAAAAAAAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAAAAAAAAAAABAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEAAAAAAAAAAAEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQAAAAAAAAAAAQEBAQEBAQEBAQEBAAAAAAAAAAAAAAAAAAAAAAAAAAABAQEBAQEBAQEBAQEAAAAAAAAAAAAAAAAAAAAAAAAAAAEBAQEBAQEBAQEBAQAAAAAAAAAAAAAAAAAAAAAAAAAAAQEBAQEBAQEBAQEBAAAAAAAAAAAAAAAAAAAAAAAAAAABAQEBAQEBAQEBAQEAAAAAAAAAAAAAAAAAAAAAAAAAAAEBAQEBAQEBAQEBAQAAAAAAAAAAAAAAAAAAAAAAAAAAAQEBAQEBAQEBAQEBAAAAAAAAAAAAAAAAAAAAAAAAAAABAQEBAQEBAQEBAQEAAAAAAAAAAAAAAAAAAAAAAAAAAAEBAQEBAQEBAQEBAQAAAAAAAAAAAAAAAAAAAQEBAQEBAQEBAQEBAQEBAQEBAAAAAAAAAAAAAAAAAAABAQEBAQEBAQEBAQEBAQEBAQEAAAAAAAAAAAAAAAAAAAEBAQEBAQEBAQEBAQEBAQEBAQAAAAAAAAAAAAAAAAAAAQEBAQEBAQEBAQEBAAAAAAAAAAAAAAAAAAAAAAAAAAABAQEBAQEBAQEBAQEAAAAAAAAAAAAAAAAAAAAAAAAAAAEBAQEBAQEBAQEBAQAAAAAAAAAAAAAAAAAAAQEBAQEBAQEBAQEBAQEBAQEBAAAAAAAAAAAAAAAAAAABAQEBAQEBAQEBAQEBAQEBAQEAAAAAAAAAAAAAAAAAAAEBAQEBAQEBAQEBAQEBAQEBAQAAAAAAAAAAAAAAAAAAAQEBAQEBAQEBAQEBAQEBAQEBAAAAAAAAAAAAAAAAAAABAQEBAQEBAQEBAQEBAQEBAQEAAAAAAAAAAAAAAAAAAAEBAQEBAQEBAQEBAQ==" - }, - "palette" : { - "originalArgb8888" : [ -265674 ], - "convertedRgb565" : [ -122 ] } }, "diagnostics" : [ ] @@ -996,14 +996,14 @@ "last_modified" : 1774359772478, "fingerprint" : "eeb7cc665386299403b7be1c272375d5077f3647c587f8033aa8c9275f840562", "metadata" : { + "palette" : { + "originalArgb8888" : [ -265674 ], + "convertedRgb565" : [ -122 ] + }, "tile" : { "width" : 32, "height" : 32, "paletteIndices" : "AQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAAAAAAAAAAABAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEAAAAAAAAAAAEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQAAAAAAAAAAAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAAAAAAAAAAABAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEAAAAAAAAAAAEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQAAAAAAAAAAAQEBAQEBAQEBAQEBAAAAAAAAAAAAAAAAAAAAAAAAAAABAQEBAQEBAQEBAQEAAAAAAAAAAAAAAAAAAAAAAAAAAAEBAQEBAQEBAQEBAQAAAAAAAAAAAAAAAAAAAAAAAAAAAQEBAQEBAQEBAQEBAAAAAAAAAAAAAAAAAAAAAAAAAAABAQEBAQEBAQEBAQEAAAAAAAAAAAAAAAAAAAAAAAAAAAEBAQEBAQEBAQEBAQAAAAAAAAAAAAAAAAAAAAAAAAAAAQEBAQEBAQEBAQEBAAAAAAAAAAAAAAAAAAAAAAAAAAABAQEBAQEBAQEBAQEAAAAAAAAAAAAAAAAAAAAAAAAAAAEBAQEBAQEBAQEBAQAAAAAAAAAAAAAAAAAAAQEBAQEBAQEBAQEBAQEBAQEBAAAAAAAAAAAAAAAAAAABAQEBAQEBAQEBAQEBAQEBAQEAAAAAAAAAAAAAAAAAAAEBAQEBAQEBAQEBAQEBAQEBAQAAAAAAAAAAAAAAAAAAAQEBAQEBAQEBAQEBAAAAAAAAAAAAAAAAAAAAAAAAAAABAQEBAQEBAQEBAQEAAAAAAAAAAAAAAAAAAAAAAAAAAAEBAQEBAQEBAQEBAQAAAAAAAAAAAAAAAAAAAQEBAQEBAQEBAQEBAQEBAQEBAAAAAAAAAAAAAAAAAAABAQEBAQEBAQEBAQEBAQEBAQEAAAAAAAAAAAAAAAAAAAEBAQEBAQEBAQEBAQEBAQEBAQAAAAAAAAAAAAAAAAAAAQEBAQEBAQEBAQEBAQEBAQEBAAAAAAAAAAAAAAAAAAABAQEBAQEBAQEBAQEBAQEBAQEAAAAAAAAAAAAAAAAAAAEBAQEBAQEBAQEBAQ==" - }, - "palette" : { - "originalArgb8888" : [ -265674 ], - "convertedRgb565" : [ -122 ] } }, "diagnostics" : [ ] @@ -1014,14 +1014,14 @@ "last_modified" : 1774359772479, "fingerprint" : "eeb7cc665386299403b7be1c272375d5077f3647c587f8033aa8c9275f840562", "metadata" : { + "palette" : { + "originalArgb8888" : [ -265674 ], + "convertedRgb565" : [ -122 ] + }, "tile" : { "width" : 32, "height" : 32, "paletteIndices" : "AQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAAAAAAAAAAABAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEAAAAAAAAAAAEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQAAAAAAAAAAAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAAAAAAAAAAABAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEAAAAAAAAAAAEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQAAAAAAAAAAAQEBAQEBAQEBAQEBAAAAAAAAAAAAAAAAAAAAAAAAAAABAQEBAQEBAQEBAQEAAAAAAAAAAAAAAAAAAAAAAAAAAAEBAQEBAQEBAQEBAQAAAAAAAAAAAAAAAAAAAAAAAAAAAQEBAQEBAQEBAQEBAAAAAAAAAAAAAAAAAAAAAAAAAAABAQEBAQEBAQEBAQEAAAAAAAAAAAAAAAAAAAAAAAAAAAEBAQEBAQEBAQEBAQAAAAAAAAAAAAAAAAAAAAAAAAAAAQEBAQEBAQEBAQEBAAAAAAAAAAAAAAAAAAAAAAAAAAABAQEBAQEBAQEBAQEAAAAAAAAAAAAAAAAAAAAAAAAAAAEBAQEBAQEBAQEBAQAAAAAAAAAAAAAAAAAAAQEBAQEBAQEBAQEBAQEBAQEBAAAAAAAAAAAAAAAAAAABAQEBAQEBAQEBAQEBAQEBAQEAAAAAAAAAAAAAAAAAAAEBAQEBAQEBAQEBAQEBAQEBAQAAAAAAAAAAAAAAAAAAAQEBAQEBAQEBAQEBAAAAAAAAAAAAAAAAAAAAAAAAAAABAQEBAQEBAQEBAQEAAAAAAAAAAAAAAAAAAAAAAAAAAAEBAQEBAQEBAQEBAQAAAAAAAAAAAAAAAAAAAQEBAQEBAQEBAQEBAQEBAQEBAAAAAAAAAAAAAAAAAAABAQEBAQEBAQEBAQEBAQEBAQEAAAAAAAAAAAAAAAAAAAEBAQEBAQEBAQEBAQEBAQEBAQAAAAAAAAAAAAAAAAAAAQEBAQEBAQEBAQEBAQEBAQEBAAAAAAAAAAAAAAAAAAABAQEBAQEBAQEBAQEBAQEBAQEAAAAAAAAAAAAAAAAAAAEBAQEBAQEBAQEBAQ==" - }, - "palette" : { - "originalArgb8888" : [ -265674 ], - "convertedRgb565" : [ -122 ] } }, "diagnostics" : [ ] @@ -1032,14 +1032,14 @@ "last_modified" : 1774359772481, "fingerprint" : "eeb7cc665386299403b7be1c272375d5077f3647c587f8033aa8c9275f840562", "metadata" : { + "palette" : { + "originalArgb8888" : [ -265674 ], + "convertedRgb565" : [ -122 ] + }, "tile" : { "width" : 32, "height" : 32, "paletteIndices" : "AQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAAAAAAAAAAABAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEAAAAAAAAAAAEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQAAAAAAAAAAAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAAAAAAAAAAABAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEAAAAAAAAAAAEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQAAAAAAAAAAAQEBAQEBAQEBAQEBAAAAAAAAAAAAAAAAAAAAAAAAAAABAQEBAQEBAQEBAQEAAAAAAAAAAAAAAAAAAAAAAAAAAAEBAQEBAQEBAQEBAQAAAAAAAAAAAAAAAAAAAAAAAAAAAQEBAQEBAQEBAQEBAAAAAAAAAAAAAAAAAAAAAAAAAAABAQEBAQEBAQEBAQEAAAAAAAAAAAAAAAAAAAAAAAAAAAEBAQEBAQEBAQEBAQAAAAAAAAAAAAAAAAAAAAAAAAAAAQEBAQEBAQEBAQEBAAAAAAAAAAAAAAAAAAAAAAAAAAABAQEBAQEBAQEBAQEAAAAAAAAAAAAAAAAAAAAAAAAAAAEBAQEBAQEBAQEBAQAAAAAAAAAAAAAAAAAAAQEBAQEBAQEBAQEBAQEBAQEBAAAAAAAAAAAAAAAAAAABAQEBAQEBAQEBAQEBAQEBAQEAAAAAAAAAAAAAAAAAAAEBAQEBAQEBAQEBAQEBAQEBAQAAAAAAAAAAAAAAAAAAAQEBAQEBAQEBAQEBAAAAAAAAAAAAAAAAAAAAAAAAAAABAQEBAQEBAQEBAQEAAAAAAAAAAAAAAAAAAAAAAAAAAAEBAQEBAQEBAQEBAQAAAAAAAAAAAAAAAAAAAQEBAQEBAQEBAQEBAQEBAQEBAAAAAAAAAAAAAAAAAAABAQEBAQEBAQEBAQEBAQEBAQEAAAAAAAAAAAAAAAAAAAEBAQEBAQEBAQEBAQEBAQEBAQAAAAAAAAAAAAAAAAAAAQEBAQEBAQEBAQEBAQEBAQEBAAAAAAAAAAAAAAAAAAABAQEBAQEBAQEBAQEBAQEBAQEAAAAAAAAAAAAAAAAAAAEBAQEBAQEBAQEBAQ==" - }, - "palette" : { - "originalArgb8888" : [ -265674 ], - "convertedRgb565" : [ -122 ] } }, "diagnostics" : [ ] @@ -1050,14 +1050,14 @@ "last_modified" : 1774359772482, "fingerprint" : "eeb7cc665386299403b7be1c272375d5077f3647c587f8033aa8c9275f840562", "metadata" : { + "palette" : { + "originalArgb8888" : [ -265674 ], + "convertedRgb565" : [ -122 ] + }, "tile" : { "width" : 32, "height" : 32, "paletteIndices" : "AQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAAAAAAAAAAABAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEAAAAAAAAAAAEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQAAAAAAAAAAAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAAAAAAAAAAABAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEAAAAAAAAAAAEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQAAAAAAAAAAAQEBAQEBAQEBAQEBAAAAAAAAAAAAAAAAAAAAAAAAAAABAQEBAQEBAQEBAQEAAAAAAAAAAAAAAAAAAAAAAAAAAAEBAQEBAQEBAQEBAQAAAAAAAAAAAAAAAAAAAAAAAAAAAQEBAQEBAQEBAQEBAAAAAAAAAAAAAAAAAAAAAAAAAAABAQEBAQEBAQEBAQEAAAAAAAAAAAAAAAAAAAAAAAAAAAEBAQEBAQEBAQEBAQAAAAAAAAAAAAAAAAAAAAAAAAAAAQEBAQEBAQEBAQEBAAAAAAAAAAAAAAAAAAAAAAAAAAABAQEBAQEBAQEBAQEAAAAAAAAAAAAAAAAAAAAAAAAAAAEBAQEBAQEBAQEBAQAAAAAAAAAAAAAAAAAAAQEBAQEBAQEBAQEBAQEBAQEBAAAAAAAAAAAAAAAAAAABAQEBAQEBAQEBAQEBAQEBAQEAAAAAAAAAAAAAAAAAAAEBAQEBAQEBAQEBAQEBAQEBAQAAAAAAAAAAAAAAAAAAAQEBAQEBAQEBAQEBAAAAAAAAAAAAAAAAAAAAAAAAAAABAQEBAQEBAQEBAQEAAAAAAAAAAAAAAAAAAAAAAAAAAAEBAQEBAQEBAQEBAQAAAAAAAAAAAAAAAAAAAQEBAQEBAQEBAQEBAQEBAQEBAAAAAAAAAAAAAAAAAAABAQEBAQEBAQEBAQEBAQEBAQEAAAAAAAAAAAAAAAAAAAEBAQEBAQEBAQEBAQEBAQEBAQAAAAAAAAAAAAAAAAAAAQEBAQEBAQEBAQEBAQEBAQEBAAAAAAAAAAAAAAAAAAABAQEBAQEBAQEBAQEBAQEBAQEAAAAAAAAAAAAAAAAAAAEBAQEBAQEBAQEBAQ==" - }, - "palette" : { - "originalArgb8888" : [ -265674 ], - "convertedRgb565" : [ -122 ] } }, "diagnostics" : [ ] @@ -1068,14 +1068,14 @@ "last_modified" : 1774359772483, "fingerprint" : "eeb7cc665386299403b7be1c272375d5077f3647c587f8033aa8c9275f840562", "metadata" : { + "palette" : { + "originalArgb8888" : [ -265674 ], + "convertedRgb565" : [ -122 ] + }, "tile" : { "width" : 32, "height" : 32, "paletteIndices" : "AQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAAAAAAAAAAABAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEAAAAAAAAAAAEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQAAAAAAAAAAAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAAAAAAAAAAABAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEAAAAAAAAAAAEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQAAAAAAAAAAAQEBAQEBAQEBAQEBAAAAAAAAAAAAAAAAAAAAAAAAAAABAQEBAQEBAQEBAQEAAAAAAAAAAAAAAAAAAAAAAAAAAAEBAQEBAQEBAQEBAQAAAAAAAAAAAAAAAAAAAAAAAAAAAQEBAQEBAQEBAQEBAAAAAAAAAAAAAAAAAAAAAAAAAAABAQEBAQEBAQEBAQEAAAAAAAAAAAAAAAAAAAAAAAAAAAEBAQEBAQEBAQEBAQAAAAAAAAAAAAAAAAAAAAAAAAAAAQEBAQEBAQEBAQEBAAAAAAAAAAAAAAAAAAAAAAAAAAABAQEBAQEBAQEBAQEAAAAAAAAAAAAAAAAAAAAAAAAAAAEBAQEBAQEBAQEBAQAAAAAAAAAAAAAAAAAAAQEBAQEBAQEBAQEBAQEBAQEBAAAAAAAAAAAAAAAAAAABAQEBAQEBAQEBAQEBAQEBAQEAAAAAAAAAAAAAAAAAAAEBAQEBAQEBAQEBAQEBAQEBAQAAAAAAAAAAAAAAAAAAAQEBAQEBAQEBAQEBAAAAAAAAAAAAAAAAAAAAAAAAAAABAQEBAQEBAQEBAQEAAAAAAAAAAAAAAAAAAAAAAAAAAAEBAQEBAQEBAQEBAQAAAAAAAAAAAAAAAAAAAQEBAQEBAQEBAQEBAQEBAQEBAAAAAAAAAAAAAAAAAAABAQEBAQEBAQEBAQEBAQEBAQEAAAAAAAAAAAAAAAAAAAEBAQEBAQEBAQEBAQEBAQEBAQAAAAAAAAAAAAAAAAAAAQEBAQEBAQEBAQEBAQEBAQEBAAAAAAAAAAAAAAAAAAABAQEBAQEBAQEBAQEBAQEBAQEAAAAAAAAAAAAAAAAAAAEBAQEBAQEBAQEBAQ==" - }, - "palette" : { - "originalArgb8888" : [ -265674 ], - "convertedRgb565" : [ -122 ] } }, "diagnostics" : [ ] @@ -1086,14 +1086,14 @@ "last_modified" : 1774359772484, "fingerprint" : "eeb7cc665386299403b7be1c272375d5077f3647c587f8033aa8c9275f840562", "metadata" : { + "palette" : { + "originalArgb8888" : [ -265674 ], + "convertedRgb565" : [ -122 ] + }, "tile" : { "width" : 32, "height" : 32, "paletteIndices" : "AQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAAAAAAAAAAABAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEAAAAAAAAAAAEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQAAAAAAAAAAAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAAAAAAAAAAABAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEAAAAAAAAAAAEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQAAAAAAAAAAAQEBAQEBAQEBAQEBAAAAAAAAAAAAAAAAAAAAAAAAAAABAQEBAQEBAQEBAQEAAAAAAAAAAAAAAAAAAAAAAAAAAAEBAQEBAQEBAQEBAQAAAAAAAAAAAAAAAAAAAAAAAAAAAQEBAQEBAQEBAQEBAAAAAAAAAAAAAAAAAAAAAAAAAAABAQEBAQEBAQEBAQEAAAAAAAAAAAAAAAAAAAAAAAAAAAEBAQEBAQEBAQEBAQAAAAAAAAAAAAAAAAAAAAAAAAAAAQEBAQEBAQEBAQEBAAAAAAAAAAAAAAAAAAAAAAAAAAABAQEBAQEBAQEBAQEAAAAAAAAAAAAAAAAAAAAAAAAAAAEBAQEBAQEBAQEBAQAAAAAAAAAAAAAAAAAAAQEBAQEBAQEBAQEBAQEBAQEBAAAAAAAAAAAAAAAAAAABAQEBAQEBAQEBAQEBAQEBAQEAAAAAAAAAAAAAAAAAAAEBAQEBAQEBAQEBAQEBAQEBAQAAAAAAAAAAAAAAAAAAAQEBAQEBAQEBAQEBAAAAAAAAAAAAAAAAAAAAAAAAAAABAQEBAQEBAQEBAQEAAAAAAAAAAAAAAAAAAAAAAAAAAAEBAQEBAQEBAQEBAQAAAAAAAAAAAAAAAAAAAQEBAQEBAQEBAQEBAQEBAQEBAAAAAAAAAAAAAAAAAAABAQEBAQEBAQEBAQEBAQEBAQEAAAAAAAAAAAAAAAAAAAEBAQEBAQEBAQEBAQEBAQEBAQAAAAAAAAAAAAAAAAAAAQEBAQEBAQEBAQEBAQEBAQEBAAAAAAAAAAAAAAAAAAABAQEBAQEBAQEBAQEBAQEBAQEAAAAAAAAAAAAAAAAAAAEBAQEBAQEBAQEBAQ==" - }, - "palette" : { - "originalArgb8888" : [ -265674 ], - "convertedRgb565" : [ -122 ] } }, "diagnostics" : [ ] @@ -1104,14 +1104,14 @@ "last_modified" : 1774359772485, "fingerprint" : "eeb7cc665386299403b7be1c272375d5077f3647c587f8033aa8c9275f840562", "metadata" : { + "palette" : { + "originalArgb8888" : [ -265674 ], + "convertedRgb565" : [ -122 ] + }, "tile" : { "width" : 32, "height" : 32, "paletteIndices" : "AQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAAAAAAAAAAABAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEAAAAAAAAAAAEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQAAAAAAAAAAAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAAAAAAAAAAABAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEAAAAAAAAAAAEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQAAAAAAAAAAAQEBAQEBAQEBAQEBAAAAAAAAAAAAAAAAAAAAAAAAAAABAQEBAQEBAQEBAQEAAAAAAAAAAAAAAAAAAAAAAAAAAAEBAQEBAQEBAQEBAQAAAAAAAAAAAAAAAAAAAAAAAAAAAQEBAQEBAQEBAQEBAAAAAAAAAAAAAAAAAAAAAAAAAAABAQEBAQEBAQEBAQEAAAAAAAAAAAAAAAAAAAAAAAAAAAEBAQEBAQEBAQEBAQAAAAAAAAAAAAAAAAAAAAAAAAAAAQEBAQEBAQEBAQEBAAAAAAAAAAAAAAAAAAAAAAAAAAABAQEBAQEBAQEBAQEAAAAAAAAAAAAAAAAAAAAAAAAAAAEBAQEBAQEBAQEBAQAAAAAAAAAAAAAAAAAAAQEBAQEBAQEBAQEBAQEBAQEBAAAAAAAAAAAAAAAAAAABAQEBAQEBAQEBAQEBAQEBAQEAAAAAAAAAAAAAAAAAAAEBAQEBAQEBAQEBAQEBAQEBAQAAAAAAAAAAAAAAAAAAAQEBAQEBAQEBAQEBAAAAAAAAAAAAAAAAAAAAAAAAAAABAQEBAQEBAQEBAQEAAAAAAAAAAAAAAAAAAAAAAAAAAAEBAQEBAQEBAQEBAQAAAAAAAAAAAAAAAAAAAQEBAQEBAQEBAQEBAQEBAQEBAAAAAAAAAAAAAAAAAAABAQEBAQEBAQEBAQEBAQEBAQEAAAAAAAAAAAAAAAAAAAEBAQEBAQEBAQEBAQEBAQEBAQAAAAAAAAAAAAAAAAAAAQEBAQEBAQEBAQEBAQEBAQEBAAAAAAAAAAAAAAAAAAABAQEBAQEBAQEBAQEBAQEBAQEAAAAAAAAAAAAAAAAAAAEBAQEBAQEBAQEBAQ==" - }, - "palette" : { - "originalArgb8888" : [ -265674 ], - "convertedRgb565" : [ -122 ] } }, "diagnostics" : [ ] @@ -1122,14 +1122,14 @@ "last_modified" : 1774359772487, "fingerprint" : "eeb7cc665386299403b7be1c272375d5077f3647c587f8033aa8c9275f840562", "metadata" : { + "palette" : { + "originalArgb8888" : [ -265674 ], + "convertedRgb565" : [ -122 ] + }, "tile" : { "width" : 32, "height" : 32, "paletteIndices" : "AQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAAAAAAAAAAABAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEAAAAAAAAAAAEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQAAAAAAAAAAAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAAAAAAAAAAABAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEAAAAAAAAAAAEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQAAAAAAAAAAAQEBAQEBAQEBAQEBAAAAAAAAAAAAAAAAAAAAAAAAAAABAQEBAQEBAQEBAQEAAAAAAAAAAAAAAAAAAAAAAAAAAAEBAQEBAQEBAQEBAQAAAAAAAAAAAAAAAAAAAAAAAAAAAQEBAQEBAQEBAQEBAAAAAAAAAAAAAAAAAAAAAAAAAAABAQEBAQEBAQEBAQEAAAAAAAAAAAAAAAAAAAAAAAAAAAEBAQEBAQEBAQEBAQAAAAAAAAAAAAAAAAAAAAAAAAAAAQEBAQEBAQEBAQEBAAAAAAAAAAAAAAAAAAAAAAAAAAABAQEBAQEBAQEBAQEAAAAAAAAAAAAAAAAAAAAAAAAAAAEBAQEBAQEBAQEBAQAAAAAAAAAAAAAAAAAAAQEBAQEBAQEBAQEBAQEBAQEBAAAAAAAAAAAAAAAAAAABAQEBAQEBAQEBAQEBAQEBAQEAAAAAAAAAAAAAAAAAAAEBAQEBAQEBAQEBAQEBAQEBAQAAAAAAAAAAAAAAAAAAAQEBAQEBAQEBAQEBAAAAAAAAAAAAAAAAAAAAAAAAAAABAQEBAQEBAQEBAQEAAAAAAAAAAAAAAAAAAAAAAAAAAAEBAQEBAQEBAQEBAQAAAAAAAAAAAAAAAAAAAQEBAQEBAQEBAQEBAQEBAQEBAAAAAAAAAAAAAAAAAAABAQEBAQEBAQEBAQEBAQEBAQEAAAAAAAAAAAAAAAAAAAEBAQEBAQEBAQEBAQEBAQEBAQAAAAAAAAAAAAAAAAAAAQEBAQEBAQEBAQEBAQEBAQEBAAAAAAAAAAAAAAAAAAABAQEBAQEBAQEBAQEBAQEBAQEAAAAAAAAAAAAAAAAAAAEBAQEBAQEBAQEBAQ==" - }, - "palette" : { - "originalArgb8888" : [ -265674 ], - "convertedRgb565" : [ -122 ] } }, "diagnostics" : [ ] @@ -1140,14 +1140,14 @@ "last_modified" : 1774359772488, "fingerprint" : "eeb7cc665386299403b7be1c272375d5077f3647c587f8033aa8c9275f840562", "metadata" : { + "palette" : { + "originalArgb8888" : [ -265674 ], + "convertedRgb565" : [ -122 ] + }, "tile" : { "width" : 32, "height" : 32, "paletteIndices" : "AQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAAAAAAAAAAABAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEAAAAAAAAAAAEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQAAAAAAAAAAAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAAAAAAAAAAABAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEAAAAAAAAAAAEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQAAAAAAAAAAAQEBAQEBAQEBAQEBAAAAAAAAAAAAAAAAAAAAAAAAAAABAQEBAQEBAQEBAQEAAAAAAAAAAAAAAAAAAAAAAAAAAAEBAQEBAQEBAQEBAQAAAAAAAAAAAAAAAAAAAAAAAAAAAQEBAQEBAQEBAQEBAAAAAAAAAAAAAAAAAAAAAAAAAAABAQEBAQEBAQEBAQEAAAAAAAAAAAAAAAAAAAAAAAAAAAEBAQEBAQEBAQEBAQAAAAAAAAAAAAAAAAAAAAAAAAAAAQEBAQEBAQEBAQEBAAAAAAAAAAAAAAAAAAAAAAAAAAABAQEBAQEBAQEBAQEAAAAAAAAAAAAAAAAAAAAAAAAAAAEBAQEBAQEBAQEBAQAAAAAAAAAAAAAAAAAAAQEBAQEBAQEBAQEBAQEBAQEBAAAAAAAAAAAAAAAAAAABAQEBAQEBAQEBAQEBAQEBAQEAAAAAAAAAAAAAAAAAAAEBAQEBAQEBAQEBAQEBAQEBAQAAAAAAAAAAAAAAAAAAAQEBAQEBAQEBAQEBAAAAAAAAAAAAAAAAAAAAAAAAAAABAQEBAQEBAQEBAQEAAAAAAAAAAAAAAAAAAAAAAAAAAAEBAQEBAQEBAQEBAQAAAAAAAAAAAAAAAAAAAQEBAQEBAQEBAQEBAQEBAQEBAAAAAAAAAAAAAAAAAAABAQEBAQEBAQEBAQEBAQEBAQEAAAAAAAAAAAAAAAAAAAEBAQEBAQEBAQEBAQEBAQEBAQAAAAAAAAAAAAAAAAAAAQEBAQEBAQEBAQEBAQEBAQEBAAAAAAAAAAAAAAAAAAABAQEBAQEBAQEBAQEBAQEBAQEAAAAAAAAAAAAAAAAAAAEBAQEBAQEBAQEBAQ==" - }, - "palette" : { - "originalArgb8888" : [ -265674 ], - "convertedRgb565" : [ -122 ] } }, "diagnostics" : [ ] @@ -1158,14 +1158,14 @@ "last_modified" : 1774359772489, "fingerprint" : "eeb7cc665386299403b7be1c272375d5077f3647c587f8033aa8c9275f840562", "metadata" : { + "palette" : { + "originalArgb8888" : [ -265674 ], + "convertedRgb565" : [ -122 ] + }, "tile" : { "width" : 32, "height" : 32, "paletteIndices" : "AQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAAAAAAAAAAABAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEAAAAAAAAAAAEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQAAAAAAAAAAAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAAAAAAAAAAABAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEAAAAAAAAAAAEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQAAAAAAAAAAAQEBAQEBAQEBAQEBAAAAAAAAAAAAAAAAAAAAAAAAAAABAQEBAQEBAQEBAQEAAAAAAAAAAAAAAAAAAAAAAAAAAAEBAQEBAQEBAQEBAQAAAAAAAAAAAAAAAAAAAAAAAAAAAQEBAQEBAQEBAQEBAAAAAAAAAAAAAAAAAAAAAAAAAAABAQEBAQEBAQEBAQEAAAAAAAAAAAAAAAAAAAAAAAAAAAEBAQEBAQEBAQEBAQAAAAAAAAAAAAAAAAAAAAAAAAAAAQEBAQEBAQEBAQEBAAAAAAAAAAAAAAAAAAAAAAAAAAABAQEBAQEBAQEBAQEAAAAAAAAAAAAAAAAAAAAAAAAAAAEBAQEBAQEBAQEBAQAAAAAAAAAAAAAAAAAAAQEBAQEBAQEBAQEBAQEBAQEBAAAAAAAAAAAAAAAAAAABAQEBAQEBAQEBAQEBAQEBAQEAAAAAAAAAAAAAAAAAAAEBAQEBAQEBAQEBAQEBAQEBAQAAAAAAAAAAAAAAAAAAAQEBAQEBAQEBAQEBAAAAAAAAAAAAAAAAAAAAAAAAAAABAQEBAQEBAQEBAQEAAAAAAAAAAAAAAAAAAAAAAAAAAAEBAQEBAQEBAQEBAQAAAAAAAAAAAAAAAAAAAQEBAQEBAQEBAQEBAQEBAQEBAAAAAAAAAAAAAAAAAAABAQEBAQEBAQEBAQEBAQEBAQEAAAAAAAAAAAAAAAAAAAEBAQEBAQEBAQEBAQEBAQEBAQAAAAAAAAAAAAAAAAAAAQEBAQEBAQEBAQEBAQEBAQEBAAAAAAAAAAAAAAAAAAABAQEBAQEBAQEBAQEBAQEBAQEAAAAAAAAAAAAAAAAAAAEBAQEBAQEBAQEBAQ==" - }, - "palette" : { - "originalArgb8888" : [ -265674 ], - "convertedRgb565" : [ -122 ] } }, "diagnostics" : [ ] @@ -1176,14 +1176,14 @@ "last_modified" : 1774359772491, "fingerprint" : "eeb7cc665386299403b7be1c272375d5077f3647c587f8033aa8c9275f840562", "metadata" : { + "palette" : { + "originalArgb8888" : [ -265674 ], + "convertedRgb565" : [ -122 ] + }, "tile" : { "width" : 32, "height" : 32, "paletteIndices" : "AQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAAAAAAAAAAABAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEAAAAAAAAAAAEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQAAAAAAAAAAAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAAAAAAAAAAABAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEAAAAAAAAAAAEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQAAAAAAAAAAAQEBAQEBAQEBAQEBAAAAAAAAAAAAAAAAAAAAAAAAAAABAQEBAQEBAQEBAQEAAAAAAAAAAAAAAAAAAAAAAAAAAAEBAQEBAQEBAQEBAQAAAAAAAAAAAAAAAAAAAAAAAAAAAQEBAQEBAQEBAQEBAAAAAAAAAAAAAAAAAAAAAAAAAAABAQEBAQEBAQEBAQEAAAAAAAAAAAAAAAAAAAAAAAAAAAEBAQEBAQEBAQEBAQAAAAAAAAAAAAAAAAAAAAAAAAAAAQEBAQEBAQEBAQEBAAAAAAAAAAAAAAAAAAAAAAAAAAABAQEBAQEBAQEBAQEAAAAAAAAAAAAAAAAAAAAAAAAAAAEBAQEBAQEBAQEBAQAAAAAAAAAAAAAAAAAAAQEBAQEBAQEBAQEBAQEBAQEBAAAAAAAAAAAAAAAAAAABAQEBAQEBAQEBAQEBAQEBAQEAAAAAAAAAAAAAAAAAAAEBAQEBAQEBAQEBAQEBAQEBAQAAAAAAAAAAAAAAAAAAAQEBAQEBAQEBAQEBAAAAAAAAAAAAAAAAAAAAAAAAAAABAQEBAQEBAQEBAQEAAAAAAAAAAAAAAAAAAAAAAAAAAAEBAQEBAQEBAQEBAQAAAAAAAAAAAAAAAAAAAQEBAQEBAQEBAQEBAQEBAQEBAAAAAAAAAAAAAAAAAAABAQEBAQEBAQEBAQEBAQEBAQEAAAAAAAAAAAAAAAAAAAEBAQEBAQEBAQEBAQEBAQEBAQAAAAAAAAAAAAAAAAAAAQEBAQEBAQEBAQEBAQEBAQEBAAAAAAAAAAAAAAAAAAABAQEBAQEBAQEBAQEBAQEBAQEAAAAAAAAAAAAAAAAAAAEBAQEBAQEBAQEBAQ==" - }, - "palette" : { - "originalArgb8888" : [ -265674 ], - "convertedRgb565" : [ -122 ] } }, "diagnostics" : [ ] @@ -1194,14 +1194,14 @@ "last_modified" : 1774359772492, "fingerprint" : "eeb7cc665386299403b7be1c272375d5077f3647c587f8033aa8c9275f840562", "metadata" : { + "palette" : { + "originalArgb8888" : [ -265674 ], + "convertedRgb565" : [ -122 ] + }, "tile" : { "width" : 32, "height" : 32, "paletteIndices" : "AQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAAAAAAAAAAABAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEAAAAAAAAAAAEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQAAAAAAAAAAAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAAAAAAAAAAABAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEAAAAAAAAAAAEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQAAAAAAAAAAAQEBAQEBAQEBAQEBAAAAAAAAAAAAAAAAAAAAAAAAAAABAQEBAQEBAQEBAQEAAAAAAAAAAAAAAAAAAAAAAAAAAAEBAQEBAQEBAQEBAQAAAAAAAAAAAAAAAAAAAAAAAAAAAQEBAQEBAQEBAQEBAAAAAAAAAAAAAAAAAAAAAAAAAAABAQEBAQEBAQEBAQEAAAAAAAAAAAAAAAAAAAAAAAAAAAEBAQEBAQEBAQEBAQAAAAAAAAAAAAAAAAAAAAAAAAAAAQEBAQEBAQEBAQEBAAAAAAAAAAAAAAAAAAAAAAAAAAABAQEBAQEBAQEBAQEAAAAAAAAAAAAAAAAAAAAAAAAAAAEBAQEBAQEBAQEBAQAAAAAAAAAAAAAAAAAAAQEBAQEBAQEBAQEBAQEBAQEBAAAAAAAAAAAAAAAAAAABAQEBAQEBAQEBAQEBAQEBAQEAAAAAAAAAAAAAAAAAAAEBAQEBAQEBAQEBAQEBAQEBAQAAAAAAAAAAAAAAAAAAAQEBAQEBAQEBAQEBAAAAAAAAAAAAAAAAAAAAAAAAAAABAQEBAQEBAQEBAQEAAAAAAAAAAAAAAAAAAAAAAAAAAAEBAQEBAQEBAQEBAQAAAAAAAAAAAAAAAAAAAQEBAQEBAQEBAQEBAQEBAQEBAAAAAAAAAAAAAAAAAAABAQEBAQEBAQEBAQEBAQEBAQEAAAAAAAAAAAAAAAAAAAEBAQEBAQEBAQEBAQEBAQEBAQAAAAAAAAAAAAAAAAAAAQEBAQEBAQEBAQEBAQEBAQEBAAAAAAAAAAAAAAAAAAABAQEBAQEBAQEBAQEBAQEBAQEAAAAAAAAAAAAAAAAAAAEBAQEBAQEBAQEBAQ==" - }, - "palette" : { - "originalArgb8888" : [ -265674 ], - "convertedRgb565" : [ -122 ] } }, "diagnostics" : [ ] @@ -1212,14 +1212,14 @@ "last_modified" : 1774359772493, "fingerprint" : "eeb7cc665386299403b7be1c272375d5077f3647c587f8033aa8c9275f840562", "metadata" : { + "palette" : { + "originalArgb8888" : [ -265674 ], + "convertedRgb565" : [ -122 ] + }, "tile" : { "width" : 32, "height" : 32, "paletteIndices" : "AQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAAAAAAAAAAABAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEAAAAAAAAAAAEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQAAAAAAAAAAAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAAAAAAAAAAABAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEAAAAAAAAAAAEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQAAAAAAAAAAAQEBAQEBAQEBAQEBAAAAAAAAAAAAAAAAAAAAAAAAAAABAQEBAQEBAQEBAQEAAAAAAAAAAAAAAAAAAAAAAAAAAAEBAQEBAQEBAQEBAQAAAAAAAAAAAAAAAAAAAAAAAAAAAQEBAQEBAQEBAQEBAAAAAAAAAAAAAAAAAAAAAAAAAAABAQEBAQEBAQEBAQEAAAAAAAAAAAAAAAAAAAAAAAAAAAEBAQEBAQEBAQEBAQAAAAAAAAAAAAAAAAAAAAAAAAAAAQEBAQEBAQEBAQEBAAAAAAAAAAAAAAAAAAAAAAAAAAABAQEBAQEBAQEBAQEAAAAAAAAAAAAAAAAAAAAAAAAAAAEBAQEBAQEBAQEBAQAAAAAAAAAAAAAAAAAAAQEBAQEBAQEBAQEBAQEBAQEBAAAAAAAAAAAAAAAAAAABAQEBAQEBAQEBAQEBAQEBAQEAAAAAAAAAAAAAAAAAAAEBAQEBAQEBAQEBAQEBAQEBAQAAAAAAAAAAAAAAAAAAAQEBAQEBAQEBAQEBAAAAAAAAAAAAAAAAAAAAAAAAAAABAQEBAQEBAQEBAQEAAAAAAAAAAAAAAAAAAAAAAAAAAAEBAQEBAQEBAQEBAQAAAAAAAAAAAAAAAAAAAQEBAQEBAQEBAQEBAQEBAQEBAAAAAAAAAAAAAAAAAAABAQEBAQEBAQEBAQEBAQEBAQEAAAAAAAAAAAAAAAAAAAEBAQEBAQEBAQEBAQEBAQEBAQAAAAAAAAAAAAAAAAAAAQEBAQEBAQEBAQEBAQEBAQEBAAAAAAAAAAAAAAAAAAABAQEBAQEBAQEBAQEBAQEBAQEAAAAAAAAAAAAAAAAAAAEBAQEBAQEBAQEBAQ==" - }, - "palette" : { - "originalArgb8888" : [ -265674 ], - "convertedRgb565" : [ -122 ] } }, "diagnostics" : [ ] @@ -1230,14 +1230,14 @@ "last_modified" : 1774359772494, "fingerprint" : "eeb7cc665386299403b7be1c272375d5077f3647c587f8033aa8c9275f840562", "metadata" : { + "palette" : { + "originalArgb8888" : [ -265674 ], + "convertedRgb565" : [ -122 ] + }, "tile" : { "width" : 32, "height" : 32, "paletteIndices" : "AQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAAAAAAAAAAABAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEAAAAAAAAAAAEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQAAAAAAAAAAAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAAAAAAAAAAABAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEAAAAAAAAAAAEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQAAAAAAAAAAAQEBAQEBAQEBAQEBAAAAAAAAAAAAAAAAAAAAAAAAAAABAQEBAQEBAQEBAQEAAAAAAAAAAAAAAAAAAAAAAAAAAAEBAQEBAQEBAQEBAQAAAAAAAAAAAAAAAAAAAAAAAAAAAQEBAQEBAQEBAQEBAAAAAAAAAAAAAAAAAAAAAAAAAAABAQEBAQEBAQEBAQEAAAAAAAAAAAAAAAAAAAAAAAAAAAEBAQEBAQEBAQEBAQAAAAAAAAAAAAAAAAAAAAAAAAAAAQEBAQEBAQEBAQEBAAAAAAAAAAAAAAAAAAAAAAAAAAABAQEBAQEBAQEBAQEAAAAAAAAAAAAAAAAAAAAAAAAAAAEBAQEBAQEBAQEBAQAAAAAAAAAAAAAAAAAAAQEBAQEBAQEBAQEBAQEBAQEBAAAAAAAAAAAAAAAAAAABAQEBAQEBAQEBAQEBAQEBAQEAAAAAAAAAAAAAAAAAAAEBAQEBAQEBAQEBAQEBAQEBAQAAAAAAAAAAAAAAAAAAAQEBAQEBAQEBAQEBAAAAAAAAAAAAAAAAAAAAAAAAAAABAQEBAQEBAQEBAQEAAAAAAAAAAAAAAAAAAAAAAAAAAAEBAQEBAQEBAQEBAQAAAAAAAAAAAAAAAAAAAQEBAQEBAQEBAQEBAQEBAQEBAAAAAAAAAAAAAAAAAAABAQEBAQEBAQEBAQEBAQEBAQEAAAAAAAAAAAAAAAAAAAEBAQEBAQEBAQEBAQEBAQEBAQAAAAAAAAAAAAAAAAAAAQEBAQEBAQEBAQEBAQEBAQEBAAAAAAAAAAAAAAAAAAABAQEBAQEBAQEBAQEBAQEBAQEAAAAAAAAAAAAAAAAAAAEBAQEBAQEBAQEBAQ==" - }, - "palette" : { - "originalArgb8888" : [ -265674 ], - "convertedRgb565" : [ -122 ] } }, "diagnostics" : [ ] @@ -1248,14 +1248,14 @@ "last_modified" : 1774359772495, "fingerprint" : "eeb7cc665386299403b7be1c272375d5077f3647c587f8033aa8c9275f840562", "metadata" : { + "palette" : { + "originalArgb8888" : [ -265674 ], + "convertedRgb565" : [ -122 ] + }, "tile" : { "width" : 32, "height" : 32, "paletteIndices" : "AQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAAAAAAAAAAABAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEAAAAAAAAAAAEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQAAAAAAAAAAAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAAAAAAAAAAABAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEAAAAAAAAAAAEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQAAAAAAAAAAAQEBAQEBAQEBAQEBAAAAAAAAAAAAAAAAAAAAAAAAAAABAQEBAQEBAQEBAQEAAAAAAAAAAAAAAAAAAAAAAAAAAAEBAQEBAQEBAQEBAQAAAAAAAAAAAAAAAAAAAAAAAAAAAQEBAQEBAQEBAQEBAAAAAAAAAAAAAAAAAAAAAAAAAAABAQEBAQEBAQEBAQEAAAAAAAAAAAAAAAAAAAAAAAAAAAEBAQEBAQEBAQEBAQAAAAAAAAAAAAAAAAAAAAAAAAAAAQEBAQEBAQEBAQEBAAAAAAAAAAAAAAAAAAAAAAAAAAABAQEBAQEBAQEBAQEAAAAAAAAAAAAAAAAAAAAAAAAAAAEBAQEBAQEBAQEBAQAAAAAAAAAAAAAAAAAAAQEBAQEBAQEBAQEBAQEBAQEBAAAAAAAAAAAAAAAAAAABAQEBAQEBAQEBAQEBAQEBAQEAAAAAAAAAAAAAAAAAAAEBAQEBAQEBAQEBAQEBAQEBAQAAAAAAAAAAAAAAAAAAAQEBAQEBAQEBAQEBAAAAAAAAAAAAAAAAAAAAAAAAAAABAQEBAQEBAQEBAQEAAAAAAAAAAAAAAAAAAAAAAAAAAAEBAQEBAQEBAQEBAQAAAAAAAAAAAAAAAAAAAQEBAQEBAQEBAQEBAQEBAQEBAAAAAAAAAAAAAAAAAAABAQEBAQEBAQEBAQEBAQEBAQEAAAAAAAAAAAAAAAAAAAEBAQEBAQEBAQEBAQEBAQEBAQAAAAAAAAAAAAAAAAAAAQEBAQEBAQEBAQEBAQEBAQEBAAAAAAAAAAAAAAAAAAABAQEBAQEBAQEBAQEBAQEBAQEAAAAAAAAAAAAAAAAAAAEBAQEBAQEBAQEBAQ==" - }, - "palette" : { - "originalArgb8888" : [ -265674 ], - "convertedRgb565" : [ -122 ] } }, "diagnostics" : [ ] @@ -1266,14 +1266,14 @@ "last_modified" : 1775797786950, "fingerprint" : "0526996900bdeef23c72fe987fb45800f11895946dcd5f0f7f8390c879069a37", "metadata" : { + "palette" : { + "originalArgb8888" : [ -265674, -1736296, -13905598, -11518505, -14439577, -2467509 ], + "convertedRgb565" : [ -122, -7149, 11912, 20986, 9548, -9527 ] + }, "tile" : { "width" : 32, "height" : 32, "paletteIndices" : "AQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQECAgIBAQEBAQEBAQEBAQEBAQEBAwMDAwMDAQEBAQEBAgICAgICAgIBAQEBAQEBAQEBAQMDAwMDAwMBAQEBAQICAgICAgICAQEBAQEBAQEBAQEBAQMDAwMDAQEBAQEBAgICAgICAgEBAQEBAQQEBAQBAQEBAQEBAQEBAQEBAQEBAgICAgIBAQEBAQEEBAQEBAQBAQEBAQEBAQEBAQEBAQEBAgECAQEBAQEBAQQEBAQEAQEBAQEBAAAAAAAAAAABAQECAQEBAQEBAQEEBAQEBAEBAQEBAQEAAAAAAAAAAAEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQAAAAAAAAAAAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAAAAAAAAAAABAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEAAAAAAAAAAAEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQAAAAAAAAAAAQEBAQEBAQEBAQEBAAAAAAAAAAAAAAAAAAAAAAAAAAABAQEBAQEBAQEBAQEAAAAAAAAAAAAAAAAAAAAAAAAAAAEBAQEBAQEBAQEBAQAAAAAAAAAAAAAAAAAAAAAAAAAAAQEBAQEBAQUBAQEBAAAAAAAAAAAAAAAAAAAAAAAAAAABAQEBAQUFBQEBAQEAAAAAAAAAAAAAAAAAAAAAAAAAAAEBAQEFBQUFBQEBAQAAAAAAAAAAAAAAAAAAAAAAAAAAAQEBBQUFBQUBAQEBAAAAAAAAAAAAAAAAAAAAAAAAAAABAQEBBQUFAQEBAQEAAAAAAAAAAAAAAAAAAAAAAAAAAAEBAQEBAQEBAQEBAQAAAAAAAAAAAAAAAAAAAQEBAQEBAQEBAQEBAQEBAQEBAAAAAAAAAAAAAAAAAAABAQEBAQEBAQEBAQEBAQEBAQEAAAAAAAAAAAAAAAAAAAEBAQEBAQYGBgYBAQEBAQEBAQAAAAAAAAAAAAAAAAAAAQEBAQEBBgYGBgEBAAAAAAAAAAAAAAAAAAAAAAAAAAABAQEBAQEGBgYGAQEAAAAAAAAAAAAAAAAAAAAAAAAAAAEBAQEBAQYGBgYBAQAAAAAAAAAAAAAAAAAAAQEBAQEBAQEBAQEBAQYGAQEBAAAAAAAAAAAAAAAAAAABAQEBAQEBAQEBAQEBAQEBAQEAAAAAAAAAAAAAAAAAAAEBAQEBAQEBAQEBAQEBAQEBAQAAAAAAAAAAAAAAAAAAAQEBAQEBAQEBAQEBAQEBAQEBAAAAAAAAAAAAAAAAAAABAQEBAQEBAQEBAQEBAQEBAQEAAAAAAAAAAAAAAAAAAAEBAQEBAQEBAQEBAQ==" - }, - "palette" : { - "originalArgb8888" : [ -265674, -1736296, -13905598, -11518505, -14439577, -2467509 ], - "convertedRgb565" : [ -122, -7149, 11912, 20986, 9548, -9527 ] } }, "diagnostics" : [ ] @@ -1314,14 +1314,14 @@ "last_modified" : 1775797786770, "fingerprint" : "aa7d241deabcebe29a6096e14eaf16fdc06cf06380c11a507620b00fc7bff094", "metadata" : { + "palette" : { + "originalArgb8888" : [ -265674 ], + "convertedRgb565" : [ -122 ] + }, "tile" : { "width" : 16, "height" : 16, "paletteIndices" : "AQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAAAAAAEBAQEBAQEBAQEBAQAAAAABAQEBAQEBAQEBAQEAAAAAAQEBAQEBAAAAAAAAAAAAAAEBAQEBAQAAAAAAAAAAAAABAQEBAQEAAAAAAAAAAAAAAQEBAQEBAAAAAAAAAAAAAAEBAQEBAQAAAAAAAAABAQEBAQEBAQEAAAAAAAAAAQEBAQEBAAAAAAAAAAAAAAEBAQEBAQAAAAAAAAABAQEBAQEBAQEAAAAAAAAAAQEBAQEBAQEBAAAAAAAAAAEBAQEBAQ==" - }, - "palette" : { - "originalArgb8888" : [ -265674 ], - "convertedRgb565" : [ -122 ] } }, "diagnostics" : [ ] @@ -1344,14 +1344,14 @@ "last_modified" : 1775797786709, "fingerprint" : "6ca635a7906067b6a2a8460a8562718c445783e6df18b9f2c80c83c5ac569db6", "metadata" : { + "palette" : { + "originalArgb8888" : [ -130562, -14145496, -2043712, -460560, -13082456, -6252424, -10977088 ], + "convertedRgb565" : [ -2017, 10565, -6504, -34, 15125, -23345, 23576 ] + }, "tile" : { "width" : 32, "height" : 32, "paletteIndices" : "AQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQICAgICAgICAgAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAICAwMDAwMDAgAAAAAAAAAAAAACAgIAAAAAAAAAAAAAAAIEBQUFBQUDAgAAAAAAAgICAgMDAwIAAAAAAAAAAAAAAgQFAwYGBgUDAgICAgIDAwMDBQUFAwIAAAAAAAAAAAACBAUDBgYGBgUEBAQEAwUFBQUGAwMFBAICAAAAAAAAAAIEBQMGBgYGAwUFBwcFBgYGBgMDAwMFBAQCAgAAAAAAAgQFAwYGBgMDAwQEBAMGBgYGBgMDAwMHBwQDAgAAAAACBAUDBgYGAwMDAwQEAwYGBgYGAwMDBAQEBQUDAgIAAAIEBQMGBgYDAwMDBAQDBgYGBgYDAwMDBAQDAwUGAgAAAgQFAwYGBgMDAwMEBAMGBgYGBQUFBQUEBAUFBgIAAAACBAUDBgYGAwMDAwQEAwYGBQUGAwMDAwcHAwYCAAAAAAIEBQMFBQUFBQMDBAQDBgUGBgICAgICBAQCAgAAAAAAAgQFBQYGBgYDBQMEBAMFBgICAAAAAAACAgAAAAAAAAACBAMDBgICAgIDBQcHBQYCAAAAAAAAAAAAAAAAAAAAAgIDAwMCAAAAAAIEBAMDAgAAAAAAAAAAAAAAAAAAAAICAgICAgAAAAAAAAICAgIAAAAAAAAAAAAAAAAAAAAAAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQ==" - }, - "palette" : { - "originalArgb8888" : [ -130562, -14145496, -2043712, -460560, -13082456, -6252424, -10977088 ], - "convertedRgb565" : [ -2017, 10565, -6504, -34, 15125, -23345, 23576 ] } }, "diagnostics" : [ { @@ -1396,14 +1396,14 @@ "last_modified" : 1775797786706, "fingerprint" : "7feab8c868bb446afd3dd7250e70504fb0ca228f463650d2dd7c525144e0b321", "metadata" : { + "palette" : { + "originalArgb8888" : [ -16777216, -2109505, -526353, -395279, -130562, -13082456, -10911807, -6318217, -6186631, -6187143, -6318215, -13148249, -13016663, -14080215 ], + "convertedRgb565" : [ 0, -8585, -2115, -66, -2017, 15125, 23544, -25426, -23345, -23377, -25425, 13044, 15125, 10533 ] + }, "tile" : { "width" : 32, "height" : 32, "paletteIndices" : "AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAEBAQEBAQEAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAEBAgMDBAEBAQEBBQUFAAUFBQUFBQUBAQAAAAAAAAAAAAECBgcHBAIICAkBBQUFBQUFBQEBAQICAQEAAAAFBQAAAQIGAwMHBgYGBgIBBQUFBQEBCgIIBgYDBAEBBQUFAAABAgYDAwIJCQsJBgIBAQEBCAgMDA0JAgcHAwMBBQUAAAECBgMDAgsLCwsLBgMDAwIGBgkCCwILAgIHAwEFBQAAAQIGAwMCCQkJCQkCBgcHBgsLCwsCCwICAwMHAwEFAAABAgYDAgkJCQkJCQICAwMCCQkJAgkGBgYHBwcDDgUAAAECBwMCCQkJCQkJAgIDAgkJCQkGBgsCAwMDAwQEAQAAAQIHAwIJCQkJCQkCAgMCCQkJBgkLAQEBAQEBAQQBAAABAgcDAgkJCQkJAgICAwILCQYJAQEFBQUFBQUFAQEAAAECBwMCCQkJCQYGAgIDAgkGCwEFBQUFBQUFBQAAAAAAAQIHAwIJCQYGCQIGBgcMBgkBBQUFBQUFBQAAAAAAAAABAgcGBgYGCQsBAQIDBAIKAQUFBQUFBQAAAAAAAAAAAQECAwIJCQkBAQAAAQEBAQEAAAAAAAAAAAAAAAAAAAEBAQEBAQEBAQAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA==" - }, - "palette" : { - "originalArgb8888" : [ -16777216, -2109505, -526353, -395279, -130562, -13082456, -10911807, -6318217, -6186631, -6187143, -6318215, -13148249, -13016663, -14080215 ], - "convertedRgb565" : [ 0, -8585, -2115, -66, -2017, 15125, 23544, -25426, -23345, -23377, -25425, 13044, 15125, 10533 ] } }, "diagnostics" : [ ] @@ -1414,14 +1414,14 @@ "last_modified" : 1775797786710, "fingerprint" : "c363f3ef7f32d9b249c7dc8babdb3eb5aae68c524099e5e97290202b054dda71", "metadata" : { + "palette" : { + "originalArgb8888" : [ -14671840, -11431408, -9326048, -802016, -3964416, -5086944, -789517, -810399, -1863087, -10403552, -5078447 ], + "convertedRgb565" : [ 8452, 21634, 30084, -2556, -15360, -19708, -2146, -2804, -7030, 25092, -19446 ] + }, "tile" : { "width" : 32, "height" : 32, "paletteIndices" : "AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAABAQEBAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAEBAQICAwMBAQAAAAAAAAAAAAAAAAAAAAAAAAAAAAABBAQBAgIDAwMCAQAAAAAAAAAAAAAAAAAAAAAAAAAAAQUFBAQBAgIDAgICAQAAAAAAAAAAAAAAAAAAAAAAAAABBQEFBAUBAgICAgMBAAAAAAAAAAAAAAAAAAAAAAAAAAABBgEFBQUBAgECAgMBAAAAAAAAAAAAAAAAAAAAAAAAAAEGBwEFBAEBCAECAwEAAAAAAAAAAAAAAAAAAAAAAAAAAQgBBwEEAQgJAQICAQAAAAAAAAAAAAAAAAAAAAAAAAEICAEHAQQBCQYBAgIBAAAAAAAAAAAAAAAAAAAAAAAAAAEGCQkBBQEGAQUBAgEAAAAAAAAAAAAAAAAAAAAAAAAAAAEBBgYBBgEBAQABAAAAAAAAAAAAAAAAAAAAAAAAAAAAAQcBAQEBAgIBAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAECAwECAwIBAgEAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAQECAQcHBwECAQAAAAAAAAAAAAAAAAAAAAAAAAAAAAABBAEBAQEBAQECAQAAAAAAAAAAAAAAAAAAAAAAAAAAAAABAgEJCgoBAgEAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAQEBAQEJCQEBAQAAAAAAAAAAAAAAAAAAAAAAAAAAAAEBAQEKAQEBAQEBAQAAAAAAAAAAAAAAAAAAAAAAAAAAAQEBAQELCwoKAQEBAAAAAAAAAAAAAAAAAAAAAAAAAAAAAQEBAQEBAQEBAQAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAEBAQEBAQAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA==" - }, - "palette" : { - "originalArgb8888" : [ -14671840, -11431408, -9326048, -802016, -3964416, -5086944, -789517, -810399, -1863087, -10403552, -5078447 ], - "convertedRgb565" : [ 8452, 21634, 30084, -2556, -15360, -19708, -2146, -2804, -7030, 25092, -19446 ] } }, "diagnostics" : [ ] @@ -1432,14 +1432,14 @@ "last_modified" : 1775797786711, "fingerprint" : "e2130efbb9643b41a4fb62619f2713402f9622c7db040fe18d929609ef70b89a", "metadata" : { + "palette" : { + "originalArgb8888" : [ -14671840, -11431408, -9326048, -802016, -3964416, -5086944, -789517, -810399, -1863087, -10403552, -5078447 ], + "convertedRgb565" : [ 8452, 21634, 30084, -2556, -15360, -19708, -2146, -2804, -7030, 25092, -19446 ] + }, "tile" : { "width" : 32, "height" : 32, "paletteIndices" : "AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAQEBAQAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAABAQECAgMDAQEAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAQQEAQICAwMDAgEAAAAAAAAAAAAAAAAAAAAAAAAAAAEFBQQEAQICAwICAgEAAAAAAAAAAAAAAAAAAAAAAAAAAQUBBQQFAQICAgIDAQAAAAAAAAAAAAAAAAAAAAAAAAAAAQYBBQUFAQIBAgIDAQAAAAAAAAAAAAAAAAAAAAAAAAABBgcBBQQBAQgBAgMBAAAAAAAAAAAAAAAAAAAAAAAAAAEIAQcBBAEICQECAgEAAAAAAAAAAAAAAAAAAAAAAAABCAgBBwEEAQkGAQICAQAAAAAAAAAAAAAAAAAAAAAAAAABBgkJAQUBBgEFAQIBAAAAAAAAAAAAAAAAAAAAAAAAAAABAQYGAQYBAQEAAQAAAAAAAAAAAAAAAAAAAAAAAAAAAAEHAQEBAQECAQAAAAAAAAAAAAAAAAAAAAAAAAAAAAABAgEBBwMBAwMBAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAEBCQoBBwEDAgEBAAAAAAAAAAAAAAAAAAAAAAAAAAABAgEJCQoBAgIBAQIBAAAAAAAAAAAAAAAAAAAAAAAAAAECAgEBAQICAQECAQEAAAAAAAAAAAAAAAAAAAAAAAAAAAEBAgECAQECAgEBAQAAAAAAAAAAAAAAAAAAAAAAAAAAAQEBAQICAgEBAQoKAQAAAAAAAAAAAAAAAAAAAAAAAAEBAQEBAQEBAQELCwoBAAAAAAAAAAAAAAAAAAAAAAAAAQEBAQEBAQEBAQsLAQEAAAAAAAAAAAAAAAAAAAAAAAAAAQEBAQEBAQEBAQEBAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAEBAQEBAQAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA==" - }, - "palette" : { - "originalArgb8888" : [ -14671840, -11431408, -9326048, -802016, -3964416, -5086944, -789517, -810399, -1863087, -10403552, -5078447 ], - "convertedRgb565" : [ 8452, 21634, 30084, -2556, -15360, -19708, -2146, -2804, -7030, 25092, -19446 ] } }, "diagnostics" : [ ] @@ -1450,14 +1450,14 @@ "last_modified" : 1775797786713, "fingerprint" : "9216dfc6a6226fac398e9f781550d23fbfaa65bd377cdda69187149beca114ec", "metadata" : { + "palette" : { + "originalArgb8888" : [ -14671840, -11431408, -9326048, -802016, -3964416, -5086944, -789517, -810399, -1863087, -10403552, -5078447 ], + "convertedRgb565" : [ 8452, 21634, 30084, -2556, -15360, -19708, -2146, -2804, -7030, 25092, -19446 ] + }, "tile" : { "width" : 32, "height" : 32, "paletteIndices" : "AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAQEBAQAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAEBAQECAgMDAQEAAAEBAAAAAAAAAAAAAAAAAAAAAAABBAQEAQICAwMDAgEBAwEAAAAAAAAAAAAAAAAAAAAAAAEFBQQEAQICAwICAQIDAQAAAAAAAAAAAAAAAAAAAAAAAAEBBQQFAQICAgICAwEBAAAAAAAAAAAAAAAAAAAAAAAAAQYBBQUFAQIBAgICAQAAAAAAAAAAAAAAAAAAAAAAAAABBgcBBQQFAQgBAQEBAAAAAAAAAAAAAAAAAAAAAAAAAAEIAQcBBAUBCQEBBQUBAAAAAAAAAAAAAAAAAAAAAAABCAgBBwgBBAUBAQUBAAAAAAAAAAAAAAAAAAAAAAAAAAABBgkJBgYBAQEBAQAAAAAAAAAAAAAAAAAAAAAAAAAAAAABAQYGBgYBAQAAAAAAAAAAAAAAAAAAAAAAAAAAAAABAQEBAQEBAQMBAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAEJCgEHAwECAwEBAQAAAAAAAAAAAAAAAAAAAAAAAAABAQkKAQcCAQIDAQEBAQAAAAAAAAAAAAAAAAAAAAAAAAEKAQEBAQECAgEBAgELAQAAAAAAAAAAAAAAAAAAAAAAAQEKAQICAQEBAgIBAQoLAQAAAAAAAAAAAAAAAAAAAAAAAQEBAQECAgICAQEAAQEAAAAAAAAAAAAAAAAAAAAAAAAAAQEBAQEBAQEBAQAAAAAAAAAAAAAAAAAAAAAAAAAAAAEBAQEBAQEBAQEBAQAAAAAAAAAAAAAAAAAAAAAAAAAAAQEBAQEBAQEBAQEBAAAAAAAAAAAAAAAAAAAAAAAAAAAAAQEBAQEBAQEBAQAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAEBAQEBAQAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA==" - }, - "palette" : { - "originalArgb8888" : [ -14671840, -11431408, -9326048, -802016, -3964416, -5086944, -789517, -810399, -1863087, -10403552, -5078447 ], - "convertedRgb565" : [ 8452, 21634, 30084, -2556, -15360, -19708, -2146, -2804, -7030, 25092, -19446 ] } }, "diagnostics" : [ ] @@ -1468,14 +1468,14 @@ "last_modified" : 1775797786712, "fingerprint" : "ebc4b7ca7bb1455288681c5d71424f60f658a44cb343d0c3934329cec676c867", "metadata" : { + "palette" : { + "originalArgb8888" : [ -14671840, -11431408, -9326048, -802016, -3964416, -5086944, -789517, -810399, -1863087, -10403552, -5078447 ], + "convertedRgb565" : [ 8452, 21634, 30084, -2556, -15360, -19708, -2146, -2804, -7030, 25092, -19446 ] + }, "tile" : { "width" : 32, "height" : 32, "paletteIndices" : "AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAABAQEBAAAAAAEBAAAAAAAAAAAAAAAAAAAAAAAAAAEBAQICAwMBAQEBAwEAAAAAAAAAAAAAAAAAAAAAAAABBAQBAgIDAwMCAQMDAQAAAAAAAAAAAAAAAAAAAAAAAQUFBAQBAgIDAgICAwIBAAAAAAAAAAAAAAAAAAAAAAABBQEFBAUBAgICAgMCAQAAAAAAAAAAAAAAAAAAAAAAAAABBgEFBQUBAgECAgIBAAAAAAAAAAAAAAAAAAAAAAAAAAEGBwEFBAUBCAEBAQAAAAAAAAAAAAAAAAAAAAAAAAAAAQgBBwEEBQEJAQEAAAAAAAAAAAAAAAAAAAAAAAAAAAEICAEHCQEEBQEFAQAAAAAAAAAAAAAAAAAAAAAAAAAAAQEBCQkGBgEBAQUBAAAAAAAAAAAAAAAAAAAAAAAAAAABCQoBAQEGBgEBAQUBAAAAAAAAAAAAAAAAAAAAAAAAAAEKCgEHAgEBAQMBAQAAAAAAAAAAAAAAAAAAAAAAAAAAAAEBBwICAQIDAwEBAAAAAAAAAAAAAAAAAAAAAAAAAAABAQEBAQECAgMBAQIBAAAAAAAAAAAAAAAAAAAAAAAAAQoBAQIBAgICAgECAQEAAAAAAAAAAAAAAAAAAAAAAAABCgoBAgIBAQEBAgELAQAAAAAAAAAAAAAAAAAAAAAAAAEBAQEBAQICAgIBAQEAAAAAAAAAAAAAAAAAAAAAAAAAAAEBAQEBAQEBAQEBAQAAAAAAAAAAAAAAAAAAAAAAAAAAAQEBAQEBAQEBAQEBAAAAAAAAAAAAAAAAAAAAAAAAAAAAAQEBAQEBAQEBAQAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAEBAQEBAQAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA==" - }, - "palette" : { - "originalArgb8888" : [ -14671840, -11431408, -9326048, -802016, -3964416, -5086944, -789517, -810399, -1863087, -10403552, -5078447 ], - "convertedRgb565" : [ 8452, 21634, 30084, -2556, -15360, -19708, -2146, -2804, -7030, 25092, -19446 ] } }, "diagnostics" : [ ] @@ -1486,14 +1486,14 @@ "last_modified" : 1775797786718, "fingerprint" : "c363f3ef7f32d9b249c7dc8babdb3eb5aae68c524099e5e97290202b054dda71", "metadata" : { + "palette" : { + "originalArgb8888" : [ -14671840, -11431408, -9326048, -802016, -3964416, -5086944, -789517, -810399, -1863087, -10403552, -5078447 ], + "convertedRgb565" : [ 8452, 21634, 30084, -2556, -15360, -19708, -2146, -2804, -7030, 25092, -19446 ] + }, "tile" : { "width" : 32, "height" : 32, "paletteIndices" : "AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAABAQEBAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAEBAQICAwMBAQAAAAAAAAAAAAAAAAAAAAAAAAAAAAABBAQBAgIDAwMCAQAAAAAAAAAAAAAAAAAAAAAAAAAAAQUFBAQBAgIDAgICAQAAAAAAAAAAAAAAAAAAAAAAAAABBQEFBAUBAgICAgMBAAAAAAAAAAAAAAAAAAAAAAAAAAABBgEFBQUBAgECAgMBAAAAAAAAAAAAAAAAAAAAAAAAAAEGBwEFBAEBCAECAwEAAAAAAAAAAAAAAAAAAAAAAAAAAQgBBwEEAQgJAQICAQAAAAAAAAAAAAAAAAAAAAAAAAEICAEHAQQBCQYBAgIBAAAAAAAAAAAAAAAAAAAAAAAAAAEGCQkBBQEGAQUBAgEAAAAAAAAAAAAAAAAAAAAAAAAAAAEBBgYBBgEBAQABAAAAAAAAAAAAAAAAAAAAAAAAAAAAAQcBAQEBAgIBAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAECAwECAwIBAgEAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAQECAQcHBwECAQAAAAAAAAAAAAAAAAAAAAAAAAAAAAABBAEBAQEBAQECAQAAAAAAAAAAAAAAAAAAAAAAAAAAAAABAgEJCgoBAgEAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAQEBAQEJCQEBAQAAAAAAAAAAAAAAAAAAAAAAAAAAAAEBAQEKAQEBAQEBAQAAAAAAAAAAAAAAAAAAAAAAAAAAAQEBAQELCwoKAQEBAAAAAAAAAAAAAAAAAAAAAAAAAAAAAQEBAQEBAQEBAQAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAEBAQEBAQAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA==" - }, - "palette" : { - "originalArgb8888" : [ -14671840, -11431408, -9326048, -802016, -3964416, -5086944, -789517, -810399, -1863087, -10403552, -5078447 ], - "convertedRgb565" : [ 8452, 21634, 30084, -2556, -15360, -19708, -2146, -2804, -7030, 25092, -19446 ] } }, "diagnostics" : [ ] @@ -1504,14 +1504,14 @@ "last_modified" : 1775797786717, "fingerprint" : "1ba8ce75c445396334737143e0cfa56c87a1fb64cca8ad0962192594849249eb", "metadata" : { + "palette" : { + "originalArgb8888" : [ -14671840, -11431408, -9326048, -802016, -3964416, -5086944, -789517, -810399, -1863087, -10403552 ], + "convertedRgb565" : [ 8452, 21634, 30084, -2556, -15360, -19708, -2146, -2804, -7030, 25092 ] + }, "tile" : { "width" : 32, "height" : 32, "paletteIndices" : "AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAABAQEBAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAEBAQICAwMBAQAAAAAAAAAAAAAAAAAAAAAAAAAAAAABBAQBAgIDAwMCAQAAAAAAAAAAAAAAAAAAAAAAAAAAAQUFBAQBAgIDAgICAQAAAAAAAAAAAAAAAAAAAAAAAAABBQEFBAUBAgICAgMBAAAAAAAAAAAAAAAAAAAAAAAAAAABBgEFBQUBAgECAgMBAAAAAAAAAAAAAAAAAAAAAAAAAAEGBwEFBAEBCAECAwEAAAAAAAAAAAAAAAAAAAAAAAAAAQgBBwEEAQgJAQICAQAAAAAAAAAAAAAAAAAAAAAAAAEICAEHAQQBCQYBAgIBAAAAAAAAAAAAAAAAAAAAAAAAAAEGCQkBBQEGAQUBAgEAAAAAAAAAAAAAAAAAAAAAAAAAAAEBBgYBAQEBAQABAAAAAAAAAAAAAAAAAAAAAAAAAAAAAQcBAQEDAQEAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAABAwMBAgcHAQAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAQMDAwIBAQEBAQAAAAAAAAAAAAAAAAAAAAAAAAAAAAABBAIDAgEKCgECAQAAAAAAAAAAAAAAAAAAAAAAAAAAAAECAQEBAQkJAQIBAAAAAAAAAAAAAAAAAAAAAAAAAAAAAQECAgICAQECAQoBAAAAAAAAAAAAAAAAAAAAAAAAAAABAQEBAQICAgEKCgEAAAAAAAAAAAAAAAAAAAAAAAAAAQEBAQEBAQEBCgoKAQAAAAAAAAAAAAAAAAAAAAAAAAABAQEBAQEBAQEBAQEAAAAAAAAAAAAAAAAAAAAAAAAAAAABAQEBAQEBAQEBAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAQEBAQEBAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA==" - }, - "palette" : { - "originalArgb8888" : [ -14671840, -11431408, -9326048, -802016, -3964416, -5086944, -789517, -810399, -1863087, -10403552 ], - "convertedRgb565" : [ 8452, 21634, 30084, -2556, -15360, -19708, -2146, -2804, -7030, 25092 ] } }, "diagnostics" : [ ] @@ -1522,14 +1522,14 @@ "last_modified" : 1775797786714, "fingerprint" : "5e0954447699c6d5eac7550f1a10cf520efcddad0b9fbd9a716434da9d9550d4", "metadata" : { + "palette" : { + "originalArgb8888" : [ -14671840, -11431408, -9326048, -802016, -3964416, -5086944, -789517, -810399, -1863087, -10403552, -5078447 ], + "convertedRgb565" : [ 8452, 21634, 30084, -2556, -15360, -19708, -2146, -2804, -7030, 25092, -19446 ] + }, "tile" : { "width" : 32, "height" : 32, "paletteIndices" : "AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAABAQEBAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAQEBAQICAwMBAQAAAAAAAAAAAAAAAAAAAAAAAAAAAAEEBAQBAgIDAwMCAQABAQAAAAAAAAAAAAAAAAAAAAAAAQUFBAQBAgIDAgIBAQMBAAAAAAAAAAAAAAAAAAAAAAAAAQEFBAUBAgICAgIDAwEAAAAAAAAAAAAAAAAAAAAAAAABBgEFBQUBAgECAgIBAAAAAAAAAAAAAAAAAAAAAAAAAAEGBwEFBAUBCAEBAQEAAAAAAAAAAAAAAAAAAAAAAAAAAQgBBwEEBQEJAQEFBQEAAAAAAAAAAAAAAAAAAAAAAAEICAEHCAEEBQEBBQEBAAAAAAAAAAAAAAAAAAAAAAAAAAEGCQkGBgEBAQEBAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAEBBgYGAQIDAQAAAAAAAAAAAAAAAAAAAAAAAAAAAAABCQEBAQEBAQEHAQAAAAAAAAAAAAAAAAAAAAAAAAAAAQEBBwcDAgEKCgEBAAAAAAAAAAAAAAAAAAAAAAAAAAABAgIBAwMCAQkJAQEAAAAAAAAAAAAAAAAAAAAAAAAAAQEBAQIBAgMCAQEBCgEAAAAAAAAAAAAAAAAAAAAAAAABCwsKAQIBAQECAgEKAQAAAAAAAAAAAAAAAAAAAAAAAAABCwsKAQICAgIBCgoBAAAAAAAAAAAAAAAAAAAAAAAAAAABAQEBAQEBAQEBAQAAAAAAAAAAAAAAAAAAAAAAAAAAAQEBAQEBAQEBAQEBAAAAAAAAAAAAAAAAAAAAAAAAAAABAQEBAQEBAQEBAQEAAAAAAAAAAAAAAAAAAAAAAAAAAAABAQEBAQEBAQEBAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAQEBAQEBAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA==" - }, - "palette" : { - "originalArgb8888" : [ -14671840, -11431408, -9326048, -802016, -3964416, -5086944, -789517, -810399, -1863087, -10403552, -5078447 ], - "convertedRgb565" : [ 8452, 21634, 30084, -2556, -15360, -19708, -2146, -2804, -7030, 25092, -19446 ] } }, "diagnostics" : [ ] @@ -1540,14 +1540,14 @@ "last_modified" : 1775797786716, "fingerprint" : "6104ba7f216a937994d478ed07766ec28f48ad72fdd6620508535a1f877b8ddb", "metadata" : { + "palette" : { + "originalArgb8888" : [ -14671840, -11431408, -9326048, -802016, -3964416, -5086944, -789517, -810399, -1863087, -10403552, -5078447 ], + "convertedRgb565" : [ 8452, 21634, 30084, -2556, -15360, -19708, -2146, -2804, -7030, 25092, -19446 ] + }, "tile" : { "width" : 32, "height" : 32, "paletteIndices" : "AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAABAQEBAAAAAAEBAAAAAAAAAAAAAAAAAAAAAAAAAAEBAQICAwMBAQEBAwEAAAAAAAAAAAAAAAAAAAAAAAABBAQBAgIDAwMCAQMDAQAAAAAAAAAAAAAAAAAAAAAAAQUFBAQBAgIDAgICAwIBAAAAAAAAAAAAAAAAAAAAAAABBQEFBAUBAgICAgMCAQAAAAAAAAAAAAAAAAAAAAAAAAABBgEFBQUBAgECAgIBAAAAAAAAAAAAAAAAAAAAAAAAAAEGBwEFBAUBCAEBAQAAAAAAAAAAAAAAAAAAAAAAAAAAAQgBBwEEBQEJAQEAAAAAAAAAAAAAAAAAAAAAAAAAAAEICAEHCQEEBQEFAQAAAAAAAAAAAAAAAAAAAAAAAAAAAAEGCQkGBgEBAQEBAAAAAAAAAAAAAAAAAAAAAAAAAAABAQEBBgYGAQIDAgEBAAAAAAAAAAAAAAAAAAAAAAAAAAEJAQEBAQEBAgIBAQAAAAAAAAAAAAAAAAAAAAAAAAAAAAEBBwcDAgIBAQoKAQAAAAAAAAAAAAAAAAAAAAAAAAAAAQQBAwMDAgIBCQkBAAAAAAAAAAAAAAAAAAAAAAAAAAEBAgECAwMCAQEBAQEAAAAAAAAAAAAAAAAAAAAAAAABCwYBAgEBAQECAgEKAQAAAAAAAAAAAAAAAAAAAAAAAAELCgYBAgICAgEBAQEAAAAAAAAAAAAAAAAAAAAAAAAAAAEKCgoBAQEBAQEBAQAAAAAAAAAAAAAAAAAAAAAAAAAAAQEBAQEBAQEBAQEBAAAAAAAAAAAAAAAAAAAAAAAAAAAAAQEBAQEBAQEBAQAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAEBAQEBAQAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA==" - }, - "palette" : { - "originalArgb8888" : [ -14671840, -11431408, -9326048, -802016, -3964416, -5086944, -789517, -810399, -1863087, -10403552, -5078447 ], - "convertedRgb565" : [ 8452, 21634, 30084, -2556, -15360, -19708, -2146, -2804, -7030, 25092, -19446 ] } }, "diagnostics" : [ ] @@ -1602,14 +1602,14 @@ "last_modified" : 1776965154257, "fingerprint" : "8771c3e294d0edbc8dd3aaa6995a6db32166ae6bfb3e063170cc79b298d17e71", "metadata" : { + "palette" : { + "originalArgb8888" : [ -12019640 ], + "convertedRgb565" : [ 19657 ] + }, "tile" : { "width" : 8, "height" : 8, "paletteIndices" : "AQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQ==" - }, - "palette" : { - "originalArgb8888" : [ -12019640 ], - "convertedRgb565" : [ 19657 ] } }, "diagnostics" : [ ] @@ -1620,14 +1620,14 @@ "last_modified" : 1776965154257, "fingerprint" : "5d81eef8be13043330b42b546e10beed8ba00dfaa42df67477a8778c2b9484d7", "metadata" : { + "palette" : { + "originalArgb8888" : [ -12019640, -12552128, -14129088, -14133200, -14145496, -7835584, -5730208, -10465232 ], + "convertedRgb565" : [ 19657, 17352, 11080, 10950, 10565, -29816, -21364, 25222 ] + }, "tile" : { "width" : 8, "height" : 8, "paletteIndices" : "AQEBAQEBAQEBAQEBAQICAgECAgICAgICAgMEBQUFBQQDBAUGBgYGBQMEBQYGBwcIAwQFCAYGCAgBAwUFCAgIBw==" - }, - "palette" : { - "originalArgb8888" : [ -12019640, -12552128, -14129088, -14133200, -14145496, -7835584, -5730208, -10465232 ], - "convertedRgb565" : [ 19657, 17352, 11080, 10950, 10565, -29816, -21364, 25222 ] } }, "diagnostics" : [ ] @@ -1638,14 +1638,14 @@ "last_modified" : 1776965154258, "fingerprint" : "3250840c4fe08c134ea966ce7c8fcaccae2c2a45660d7173c5e262a2e5076548", "metadata" : { + "palette" : { + "originalArgb8888" : [ -12552128, -14133200, -14145496, -10465232, -5730208, -7835584 ], + "convertedRgb565" : [ 17352, 10950, 10565, 25222, -21364, -29816 ] + }, "tile" : { "width" : 8, "height" : 8, "paletteIndices" : "AQEBAQECAwMBAQEBAgMEBQEBAQIDBAUFAQIDAwQEBAQDAwYFBQUFBQQGBQUGBgYGBQUFBgYFBQUFBgYGBQUGBg==" - }, - "palette" : { - "originalArgb8888" : [ -12552128, -14133200, -14145496, -10465232, -5730208, -7835584 ], - "convertedRgb565" : [ 17352, 10950, 10565, 25222, -21364, -29816 ] } }, "diagnostics" : [ ] @@ -1656,14 +1656,14 @@ "last_modified" : 1776965154258, "fingerprint" : "fe3ab2b7eb3b10a042de14484d53e718e6b505edb1ad19053668565bfe3a8f25", "metadata" : { + "palette" : { + "originalArgb8888" : [ -14145496, -14133200, -12552128, -5730208, -10465232, -7835584 ], + "convertedRgb565" : [ 10565, 10950, 17352, -21364, 25222, -29816 ] + }, "tile" : { "width" : 8, "height" : 8, "paletteIndices" : "AQECAwMDAwMEBQECAwMDAwQEBQECAwMDBQUFBQEBAgMEBAQEBAYBAQYGBgYEBAYFBAQEBgYEBAQGBgQEBgYGBA==" - }, - "palette" : { - "originalArgb8888" : [ -14145496, -14133200, -12552128, -5730208, -10465232, -7835584 ], - "convertedRgb565" : [ 10565, 10950, 17352, -21364, 25222, -29816 ] } }, "diagnostics" : [ ] @@ -1674,14 +1674,14 @@ "last_modified" : 1776965154259, "fingerprint" : "7fcbf90e1e9a69d6ce3be80ea1901d66c9992f68dc72e4c636dcd2ad52fa2898", "metadata" : { + "palette" : { + "originalArgb8888" : [ -12019640, -12552128, -14133200, -14145496, -14129088, -7835584, -10465232, -5730208 ], + "convertedRgb565" : [ 19657, 17352, 10950, 10565, 11080, -29816, 25222, -21364 ] + }, "tile" : { "width" : 8, "height" : 8, "paletteIndices" : "AQEBAQEBAQECAgIBAQEBAQICAgICAgIBAwQEBAQDBQIEBgYGBgQDBQcICAYGBAMFBwcGBgcEAwUIBwcHBAQFAQ==" - }, - "palette" : { - "originalArgb8888" : [ -12019640, -12552128, -14133200, -14145496, -14129088, -7835584, -10465232, -5730208 ], - "convertedRgb565" : [ 19657, 17352, 10950, 10565, 11080, -29816, 25222, -21364 ] } }, "diagnostics" : [ ] @@ -1692,14 +1692,14 @@ "last_modified" : 1776965154259, "fingerprint" : "451fc8d646049944d5aa7c7dc254636eec0151aaff6e2051059304b9d6ebc31e", "metadata" : { + "palette" : { + "originalArgb8888" : [ -12019640, -14129088, -14133200, -14145496, -10465232, -5730208, -7835584 ], + "convertedRgb565" : [ 19657, 11080, 10950, 10565, 25222, -21364, -29816 ] + }, "tile" : { "width" : 8, "height" : 8, "paletteIndices" : "AQIDBAQFBgYBAQIDBAYGBwEBAQMEBgcHAQEBBAQGBwcBAQQFBAYHBwEEBwUEBgcHBAcGBQQGBwcEBwYFBAYHBw==" - }, - "palette" : { - "originalArgb8888" : [ -12019640, -14129088, -14133200, -14145496, -10465232, -5730208, -7835584 ], - "convertedRgb565" : [ 19657, 11080, 10950, 10565, 25222, -21364, -29816 ] } }, "diagnostics" : [ ] @@ -1710,14 +1710,14 @@ "last_modified" : 1776965154260, "fingerprint" : "aa757df4600823ec6655235a1081061777124ccee74b31481bbe402e53635f53", "metadata" : { + "palette" : { + "originalArgb8888" : [ -7835584, -5730208, -10465232, -14145496 ], + "convertedRgb565" : [ -29816, -21364, 25222, 10565 ] + }, "tile" : { "width" : 8, "height" : 8, "paletteIndices" : "AQECAwMBAQEBAgIBAwMBAgICAQEBAwMCAgIBAQIDBAMCAgEBAgMEBAICAQECAwQEAgIBAQIDBAMCAgIBAwQDAg==" - }, - "palette" : { - "originalArgb8888" : [ -7835584, -5730208, -10465232, -14145496 ], - "convertedRgb565" : [ -29816, -21364, 25222, 10565 ] } }, "diagnostics" : [ ] @@ -1728,14 +1728,14 @@ "last_modified" : 1776965154260, "fingerprint" : "38162157f5685cce25b835d3a2caee3465fd2ec3ee5db2a5089d7d5ae5ea3bb7", "metadata" : { + "palette" : { + "originalArgb8888" : [ -7835584, -10465232, -5730208, -14145496 ], + "convertedRgb565" : [ -29816, 25222, -21364, 10565 ] + }, "tile" : { "width" : 8, "height" : 8, "paletteIndices" : "AQEBAgIDAQEDAQICAQMDAQMCAgEBAQMDAgQCAwEBAwMEBAIDAQEDAwQEAgMBAQMDAgQCAwEBAwMDAgQCAQMDAw==" - }, - "palette" : { - "originalArgb8888" : [ -7835584, -10465232, -5730208, -14145496 ], - "convertedRgb565" : [ -29816, 25222, -21364, 10565 ] } }, "diagnostics" : [ ] @@ -1746,14 +1746,14 @@ "last_modified" : 1776965154260, "fingerprint" : "8cab5b3d553af9ed371bd19fc624763accc90e5d926d300ba31dd8d9d6bab803", "metadata" : { + "palette" : { + "originalArgb8888" : [ -5730208, -10465232, -14145496, -14133200, -14129088, -12019640, -7835584 ], + "convertedRgb565" : [ -21364, 25222, 10565, 10950, 11080, 19657, -29816 ] + }, "tile" : { "width" : 8, "height" : 8, "paletteIndices" : "AQECAwMEBQYHAQEDBAUGBgcHAQMEBgYGBwcBAwMGBgYHBwEDAgMGBgcHAQMCBwMGBwcBAwIBBwMHBwEDAgEHAw==" - }, - "palette" : { - "originalArgb8888" : [ -5730208, -10465232, -14145496, -14133200, -14129088, -12019640, -7835584 ], - "convertedRgb565" : [ -21364, 25222, 10565, 10950, 11080, 19657, -29816 ] } }, "diagnostics" : [ ] @@ -1764,14 +1764,14 @@ "last_modified" : 1776965154261, "fingerprint" : "d9ff5a6df0f65f5fcfb8f22376beeb266d429e2c6e9c82f51c12bc6ee4c3fcdc", "metadata" : { + "palette" : { + "originalArgb8888" : [ -14145496, -10465232, -7835584, -5730208, -14133200, -14129088, -12019640 ], + "convertedRgb565" : [ 10565, 25222, -29816, -21364, 10950, 11080, 19657 ] + }, "tile" : { "width" : 8, "height" : 8, "paletteIndices" : "AQIDAgIBBAMFAQECAgEEBAUGBQECAgEEBwYFBQECAQEHBwYGBQEBAgcHBwYFAQMDBwcHBwEBAwMHBwcFAQICAw==" - }, - "palette" : { - "originalArgb8888" : [ -14145496, -10465232, -7835584, -5730208, -14133200, -14129088, -12019640 ], - "convertedRgb565" : [ 10565, 25222, -29816, -21364, 10950, 11080, 19657 ] } }, "diagnostics" : [ ] @@ -1782,14 +1782,14 @@ "last_modified" : 1776965154261, "fingerprint" : "b9ff45c77f7779a6acebcc537c2ddac0e27e91162b656a04dc4772ec5f24fc26", "metadata" : { + "palette" : { + "originalArgb8888" : [ -7835584, -5730208, -10465232, -14145496 ], + "convertedRgb565" : [ -29816, -21364, 25222, 10565 ] + }, "tile" : { "width" : 8, "height" : 8, "paletteIndices" : "AQICAwMBAQIBAQMDAgIBAQIBAQEBAgIBAgICAgEBAgIEAwMCAgEBAQMEAwMCAgEBAQMEAwMDAgIBAwMEAwMDAw==" - }, - "palette" : { - "originalArgb8888" : [ -7835584, -5730208, -10465232, -14145496 ], - "convertedRgb565" : [ -29816, -21364, 25222, 10565 ] } }, "diagnostics" : [ ] @@ -1800,14 +1800,14 @@ "last_modified" : 1776965154261, "fingerprint" : "43f370324fedccda888d49409e2a64f182f08b4143b4bdd5bafaf498feebd21a", "metadata" : { + "palette" : { + "originalArgb8888" : [ -5730208, -7835584, -10465232, -14145496 ], + "convertedRgb565" : [ -21364, -29816, 25222, 10565 ] + }, "tile" : { "width" : 8, "height" : 8, "paletteIndices" : "AQICAwMBAQICAgEBAwMCAgIBAQICAgIBAQECAgEBAQECAgIBAQMDBAICAQEDAwQDAQEDAwMEAwIDAwMDBAMDAg==" - }, - "palette" : { - "originalArgb8888" : [ -5730208, -7835584, -10465232, -14145496 ], - "convertedRgb565" : [ -21364, -29816, 25222, 10565 ] } }, "diagnostics" : [ ] @@ -1818,14 +1818,14 @@ "last_modified" : 1776965154262, "fingerprint" : "cb047e655f4e196f22ca0048149df5dcb959f895faeaeb94920182d4a2d16b38", "metadata" : { + "palette" : { + "originalArgb8888" : [ -7835584, -5730208, -14145496, -10465232, -14133200, -14129088, -12019640 ], + "convertedRgb565" : [ -29816, -21364, 10565, 25222, 10950, 11080, 19657 ] + }, "tile" : { "width" : 8, "height" : 8, "paletteIndices" : "AQIDBAQBBAMCAgMEBAMDBQIDBAQDBQYFAwMEAwUFBgcEAwMFBgYHBwEBAwUGBwcHAQEDAwcHBwcBBAQDBQcHBw==" - }, - "palette" : { - "originalArgb8888" : [ -7835584, -5730208, -14145496, -10465232, -14133200, -14129088, -12019640 ], - "convertedRgb565" : [ -29816, -21364, 10565, 25222, 10950, 11080, 19657 ] } }, "diagnostics" : [ ] @@ -1836,14 +1836,14 @@ "last_modified" : 1776965154262, "fingerprint" : "25eba17b67dd5159f5fb9d3edd531d54a44d1c76f997385840dac53517b98886", "metadata" : { + "palette" : { + "originalArgb8888" : [ -12019640, -14145496, -7835584, -10465232, -14133200, -14129088 ], + "convertedRgb565" : [ 19657, 10565, -29816, 25222, 10950, 11080 ] + }, "tile" : { "width" : 8, "height" : 8, "paletteIndices" : "AQEBAgMDBAQBAQIDAwMDBAEBAgMDAwMEAQECAwMEAgQBAQIEAgUFAgEBBQUGBQYFAQEBAQEGAQYBAQEBAQEBAQ==" - }, - "palette" : { - "originalArgb8888" : [ -12019640, -14145496, -7835584, -10465232, -14133200, -14129088 ], - "convertedRgb565" : [ 19657, 10565, -29816, 25222, 10950, 11080 ] } }, "diagnostics" : [ ] @@ -1854,14 +1854,14 @@ "last_modified" : 1776965154262, "fingerprint" : "32ca96c14290de8009fd2db623f55514bed2345b7d5881a80dd3fe6235012854", "metadata" : { + "palette" : { + "originalArgb8888" : [ -10465232, -14145496, -14133200, -7835584, -14129088, -12019640 ], + "convertedRgb565" : [ 25222, 10565, 10950, -29816, 11080, 19657 ] + }, "tile" : { "width" : 8, "height" : 8, "paletteIndices" : "AQEBAgEBAgICAQICAQIBAQICAwICAQEEAgMDAwIBAQQDAwUDAwIBAQUFBgUFAgEEBgYGBgYDAgEGBgYGBgYDAg==" - }, - "palette" : { - "originalArgb8888" : [ -10465232, -14145496, -14133200, -7835584, -14129088, -12019640 ], - "convertedRgb565" : [ 25222, 10565, 10950, -29816, 11080, 19657 ] } }, "diagnostics" : [ ] @@ -1872,14 +1872,14 @@ "last_modified" : 1776965154263, "fingerprint" : "7a093fe00c805bcf38d4facff14a6d4c2b8baeaa2d553fa8d3db9f2d76b32f3b", "metadata" : { + "palette" : { + "originalArgb8888" : [ -14145496, -10465232, -7835584, -14133200, -14129088, -12019640 ], + "convertedRgb565" : [ 10565, 25222, -29816, 10950, 11080, 19657 ] + }, "tile" : { "width" : 8, "height" : 8, "paletteIndices" : "AQECAgECAgICAgECAQECAQMCAgEBBAEBAwICAQQEBAECAgEEBAUEBAMCAQUFBgUFAgEEBgYGBgYBBAYGBgYGBg==" - }, - "palette" : { - "originalArgb8888" : [ -14145496, -10465232, -7835584, -14133200, -14129088, -12019640 ], - "convertedRgb565" : [ 10565, 25222, -29816, 10950, 11080, 19657 ] } }, "diagnostics" : [ ] @@ -1890,14 +1890,14 @@ "last_modified" : 1776965154263, "fingerprint" : "77c5277220421226d16f58b1bcfb4eaf157fa4f6c740c5aaebefaf88fb91c22e", "metadata" : { + "palette" : { + "originalArgb8888" : [ -10465232, -7835584, -14145496, -12019640, -14133200, -14129088 ], + "convertedRgb565" : [ 25222, -29816, 10565, 19657, 10950, 11080 ] + }, "tile" : { "width" : 8, "height" : 8, "paletteIndices" : "AQECAgMEBAQBAgICAgMEBAECAgICAwQEAQMBAgIDBAQDBQUDAQMEBAUGBQYFBQQEBgQGBAQEBAQEBAQEBAQEBA==" - }, - "palette" : { - "originalArgb8888" : [ -10465232, -7835584, -14145496, -12019640, -14133200, -14129088 ], - "convertedRgb565" : [ 25222, -29816, 10565, 19657, 10950, 11080 ] } }, "diagnostics" : [ ] @@ -1909,7 +1909,7 @@ "relative_path" : "scene-bank.pack-request.json", "mime_type" : "application/json", "size" : 1313159, - "last_modified" : 1777630380963, + "last_modified" : 1777631167251, "fingerprint" : "31b7a0019dc08d84af95893b349839ba2975e0f8094d8eafdc1b4c48841709f8", "metadata" : { "scenePackRequest" : { diff --git a/tools/vscode-extension/.gitignore b/tools/vscode-extension/.gitignore new file mode 100644 index 00000000..ab554d4a --- /dev/null +++ b/tools/vscode-extension/.gitignore @@ -0,0 +1,35 @@ +# Dependencies +node_modules/ + +# Build output +out/ +dist/ + +# VS Code package output +*.vsix + +# TypeScript +*.tsbuildinfo + +# Logs +npm-debug.log* +yarn-debug.log* +yarn-error.log* +pnpm-debug.log* + +# Test / coverage +coverage/ +.vscode-test/ + +# Environment / local config +.env +.env.* +!.env.example + +# OS files +.DS_Store +Thumbs.db + +# Editor local state +.vscode/settings.json +.vscode/*.log \ No newline at end of file diff --git a/tools/vscode-extension/.vscode/launch.json b/tools/vscode-extension/.vscode/launch.json new file mode 100644 index 00000000..24c92b0e --- /dev/null +++ b/tools/vscode-extension/.vscode/launch.json @@ -0,0 +1,17 @@ +{ + "version": "0.2.0", + "configurations": [ + { + "name": "Run Prometeu VS Code Extension", + "type": "extensionHost", + "request": "launch", + "args": [ + "--extensionDevelopmentPath=${workspaceFolder}" + ], + "outFiles": [ + "${workspaceFolder}/out/**/*.js" + ], + "preLaunchTask": "npm: compile" + } + ] +} \ No newline at end of file diff --git a/tools/vscode-extension/.vscode/tasks.json b/tools/vscode-extension/.vscode/tasks.json new file mode 100644 index 00000000..53ec0d6a --- /dev/null +++ b/tools/vscode-extension/.vscode/tasks.json @@ -0,0 +1,12 @@ +{ + "version": "2.0.0", + "tasks": [ + { + "type": "npm", + "script": "compile", + "group": "build", + "problemMatcher": "$tsc", + "label": "npm: compile" + } + ] +} \ No newline at end of file diff --git a/tools/vscode-extension/package-lock.json b/tools/vscode-extension/package-lock.json new file mode 100644 index 00000000..6cc8d203 --- /dev/null +++ b/tools/vscode-extension/package-lock.json @@ -0,0 +1,139 @@ +{ + "name": "prometeu-vscode-extension", + "version": "0.1.0", + "lockfileVersion": 3, + "requires": true, + "packages": { + "": { + "name": "prometeu-vscode-extension", + "version": "0.1.0", + "dependencies": { + "vscode-languageclient": "^9.0.1" + }, + "devDependencies": { + "@types/node": "^20.0.0", + "@types/vscode": "^1.90.0", + "typescript": "^5.0.0" + }, + "engines": { + "vscode": "^1.90.0" + } + }, + "node_modules/@types/node": { + "version": "20.19.39", + "resolved": "https://registry.npmjs.org/@types/node/-/node-20.19.39.tgz", + "integrity": "sha512-orrrD74MBUyK8jOAD/r0+lfa1I2MO6I+vAkmAWzMYbCcgrN4lCrmK52gRFQq/JRxfYPfonkr4b0jcY7Olqdqbw==", + "dev": true, + "license": "MIT", + "dependencies": { + "undici-types": "~6.21.0" + } + }, + "node_modules/@types/vscode": { + "version": "1.118.0", + "resolved": "https://registry.npmjs.org/@types/vscode/-/vscode-1.118.0.tgz", + "integrity": "sha512-Ah6eTlqDcwIMELEVwQMO++rJAFBRz/oLluLD/vWdYrH1KuI9kfpaM+7pg0OvvascgcJy+ghLCERAYouM4QbzGw==", + "dev": true, + "license": "MIT" + }, + "node_modules/balanced-match": { + "version": "1.0.2", + "resolved": "https://registry.npmjs.org/balanced-match/-/balanced-match-1.0.2.tgz", + "integrity": "sha512-3oSeUO0TMV67hN1AmbXsK4yaqU7tjiHlbxRDZOpH0KW9+CeX4bRAaX0Anxt0tx2MrpRpWwQaPwIlISEJhYU5Pw==", + "license": "MIT" + }, + "node_modules/brace-expansion": { + "version": "2.1.0", + "resolved": "https://registry.npmjs.org/brace-expansion/-/brace-expansion-2.1.0.tgz", + "integrity": "sha512-TN1kCZAgdgweJhWWpgKYrQaMNHcDULHkWwQIspdtjV4Y5aurRdZpjAqn6yX3FPqTA9ngHCc4hJxMAMgGfve85w==", + "license": "MIT", + "dependencies": { + "balanced-match": "^1.0.0" + } + }, + "node_modules/minimatch": { + "version": "5.1.9", + "resolved": "https://registry.npmjs.org/minimatch/-/minimatch-5.1.9.tgz", + "integrity": "sha512-7o1wEA2RyMP7Iu7GNba9vc0RWWGACJOCZBJX2GJWip0ikV+wcOsgVuY9uE8CPiyQhkGFSlhuSkZPavN7u1c2Fw==", + "license": "ISC", + "dependencies": { + "brace-expansion": "^2.0.1" + }, + "engines": { + "node": ">=10" + } + }, + "node_modules/semver": { + "version": "7.7.4", + "resolved": "https://registry.npmjs.org/semver/-/semver-7.7.4.tgz", + "integrity": "sha512-vFKC2IEtQnVhpT78h1Yp8wzwrf8CM+MzKMHGJZfBtzhZNycRFnXsHk6E5TxIkkMsgNS7mdX3AGB7x2QM2di4lA==", + "license": "ISC", + "bin": { + "semver": "bin/semver.js" + }, + "engines": { + "node": ">=10" + } + }, + "node_modules/typescript": { + "version": "5.9.3", + "resolved": "https://registry.npmjs.org/typescript/-/typescript-5.9.3.tgz", + "integrity": "sha512-jl1vZzPDinLr9eUt3J/t7V6FgNEw9QjvBPdysz9KfQDD41fQrC2Y4vKQdiaUpFT4bXlb1RHhLpp8wtm6M5TgSw==", + "dev": true, + "license": "Apache-2.0", + "bin": { + "tsc": "bin/tsc", + "tsserver": "bin/tsserver" + }, + "engines": { + "node": ">=14.17" + } + }, + "node_modules/undici-types": { + "version": "6.21.0", + "resolved": "https://registry.npmjs.org/undici-types/-/undici-types-6.21.0.tgz", + "integrity": "sha512-iwDZqg0QAGrg9Rav5H4n0M64c3mkR59cJ6wQp+7C4nI0gsmExaedaYLNO44eT4AtBBwjbTiGPMlt2Md0T9H9JQ==", + "dev": true, + "license": "MIT" + }, + "node_modules/vscode-jsonrpc": { + "version": "8.2.0", + "resolved": "https://registry.npmjs.org/vscode-jsonrpc/-/vscode-jsonrpc-8.2.0.tgz", + "integrity": "sha512-C+r0eKJUIfiDIfwJhria30+TYWPtuHJXHtI7J0YlOmKAo7ogxP20T0zxB7HZQIFhIyvoBPwWskjxrvAtfjyZfA==", + "license": "MIT", + "engines": { + "node": ">=14.0.0" + } + }, + "node_modules/vscode-languageclient": { + "version": "9.0.1", + "resolved": "https://registry.npmjs.org/vscode-languageclient/-/vscode-languageclient-9.0.1.tgz", + "integrity": "sha512-JZiimVdvimEuHh5olxhxkht09m3JzUGwggb5eRUkzzJhZ2KjCN0nh55VfiED9oez9DyF8/fz1g1iBV3h+0Z2EA==", + "license": "MIT", + "dependencies": { + "minimatch": "^5.1.0", + "semver": "^7.3.7", + "vscode-languageserver-protocol": "3.17.5" + }, + "engines": { + "vscode": "^1.82.0" + } + }, + "node_modules/vscode-languageserver-protocol": { + "version": "3.17.5", + "resolved": "https://registry.npmjs.org/vscode-languageserver-protocol/-/vscode-languageserver-protocol-3.17.5.tgz", + "integrity": "sha512-mb1bvRJN8SVznADSGWM9u/b07H7Ecg0I3OgXDuLdn307rl/J3A9YD6/eYOssqhecL27hK1IPZAsaqh00i/Jljg==", + "license": "MIT", + "dependencies": { + "vscode-jsonrpc": "8.2.0", + "vscode-languageserver-types": "3.17.5" + } + }, + "node_modules/vscode-languageserver-types": { + "version": "3.17.5", + "resolved": "https://registry.npmjs.org/vscode-languageserver-types/-/vscode-languageserver-types-3.17.5.tgz", + "integrity": "sha512-Ld1VelNuX9pdF39h2Hgaeb5hEZM2Z3jUrrMgWQAu82jMtZp7p3vJT3BzToKtZI7NgQssZje5o0zryOrhQvzQAg==", + "license": "MIT" + } + } +} diff --git a/tools/vscode-extension/package.json b/tools/vscode-extension/package.json new file mode 100644 index 00000000..6a81ca6f --- /dev/null +++ b/tools/vscode-extension/package.json @@ -0,0 +1,69 @@ +{ + "name": "prometeu-vscode-extension", + "displayName": "Prometeu VS Code Extension", + "description": "VS Code bridge for Prometeu Studio.", + "version": "0.1.0", + "private": true, + "engines": { + "vscode": "^1.90.0" + }, + "categories": [ + "Programming Languages" + ], + "activationEvents": [ + "onLanguage:pbs" + ], + "main": "./out/extension.js", + "contributes": { + "languages": [ + { + "id": "pbs", + "aliases": [ + "PBS", + "Prometeu Base Script" + ], + "extensions": [ + ".pbs", + ".barrel" + ] + } + ], + "commands": [ + { + "command": "prometeu.connectStudioLsp", + "title": "Prometeu: Connect to Studio LSP" + }, + { + "command": "prometeu.restartStudioLsp", + "title": "Prometeu: Restart Studio LSP" + } + ], + "configuration": { + "title": "Prometeu", + "properties": { + "prometeu.studio.host": { + "type": "string", + "default": "127.0.0.1", + "description": "Prometeu Studio LSP host." + }, + "prometeu.studio.port": { + "type": "number", + "default": 7777, + "description": "Prometeu Studio LSP TCP port." + } + } + } + }, + "scripts": { + "compile": "tsc -p ./", + "watch": "tsc -watch -p ./" + }, + "dependencies": { + "vscode-languageclient": "^9.0.1" + }, + "devDependencies": { + "@types/node": "^20.0.0", + "@types/vscode": "^1.90.0", + "typescript": "^5.0.0" + } +} \ No newline at end of file diff --git a/tools/vscode-extension/src/extension.ts b/tools/vscode-extension/src/extension.ts new file mode 100644 index 00000000..78d98646 --- /dev/null +++ b/tools/vscode-extension/src/extension.ts @@ -0,0 +1,159 @@ +import * as net from "node:net"; +import * as vscode from "vscode"; + +import { + LanguageClient, + LanguageClientOptions, + ServerOptions, + StreamInfo +} from "vscode-languageclient/node"; + +let client: LanguageClient | undefined; +let output: vscode.OutputChannel; + +export function activate(context: vscode.ExtensionContext): void { + output = vscode.window.createOutputChannel("Prometeu LSP"); + output.appendLine("Prometeu VS Code extension activated."); + + const connectCommand = vscode.commands.registerCommand( + "prometeu.connectStudioLsp", + async () => { + await startClient(context); + } + ); + + const restartCommand = vscode.commands.registerCommand( + "prometeu.restartStudioLsp", + async () => { + await stopClient(); + await startClient(context); + } + ); + + context.subscriptions.push(output, connectCommand, restartCommand); + + void startClient(context); +} + +export async function deactivate(): Promise { + await stopClient(); +} + +async function startClient(context: vscode.ExtensionContext): Promise { + if (client) { + output.appendLine("Prometeu LSP client is already running."); + return; + } + + const config = vscode.workspace.getConfiguration("prometeu.studio"); + + const host = config.get("host", "127.0.0.1"); + const port = config.get("port", 7777); + + output.show(true); + output.appendLine(`Connecting to Prometeu Studio LSP at ${host}:${port}...`); + + const serverOptions: ServerOptions = async (): Promise => { + return new Promise((resolve, reject) => { + const socket = net.createConnection({ host, port }); + + let settled = false; + + const connectTimeout = setTimeout(() => { + if (settled) { + return; + } + + settled = true; + socket.destroy(); + reject(new Error("Connection timed out.")); + }, 3000); + + socket.once("connect", () => { + if (settled) { + return; + } + + settled = true; + clearTimeout(connectTimeout); + + output.appendLine("TCP connection established with Prometeu Studio."); + + resolve({ + reader: socket, + writer: socket + }); + }); + + socket.once("error", (error) => { + if (settled) { + return; + } + + settled = true; + clearTimeout(connectTimeout); + + reject(error); + }); + }); + }; + + const clientOptions: LanguageClientOptions = { + documentSelector: [ + { + scheme: "file", + language: "pbs" + } + ], + synchronize: { + fileEvents: [ + vscode.workspace.createFileSystemWatcher("**/*.pbs") + ] + }, + initializationOptions: { + clientKind: "vscode", + prometeuClientVersion: context.extension.packageJSON.version + }, + outputChannel: output + }; + + client = new LanguageClient( + "prometeuStudioLsp", + "Prometeu Studio LSP", + serverOptions, + clientOptions + ); + + try { + await client.start(); + + output.appendLine("Prometeu Studio LSP client started."); + vscode.window.showInformationMessage("Connected to Prometeu Studio LSP."); + } catch (error) { + client = undefined; + + const message = error instanceof Error ? error.message : String(error); + + output.appendLine(`Failed to start Prometeu LSP client: ${message}`); + vscode.window.showErrorMessage(`Could not connect to Prometeu Studio LSP: ${message}`); + } +} + +async function stopClient(): Promise { + if (!client) { + return; + } + + const currentClient = client; + client = undefined; + + output.appendLine("Stopping Prometeu Studio LSP client..."); + + try { + await currentClient.stop(); + output.appendLine("Prometeu Studio LSP client stopped."); + } catch (error) { + const message = error instanceof Error ? error.message : String(error); + output.appendLine(`Failed to stop Prometeu LSP client cleanly: ${message}`); + } +} \ No newline at end of file diff --git a/tools/vscode-extension/tsconfig.json b/tools/vscode-extension/tsconfig.json new file mode 100644 index 00000000..5864bac8 --- /dev/null +++ b/tools/vscode-extension/tsconfig.json @@ -0,0 +1,20 @@ +{ + "compilerOptions": { + "module": "Node16", + "target": "ES2022", + "lib": [ + "ES2022" + ], + "outDir": "out", + "rootDir": "src", + "sourceMap": true, + "strict": true, + "moduleResolution": "Node16", + "esModuleInterop": true, + "skipLibCheck": true + }, + "exclude": [ + "node_modules", + ".vscode-test" + ] +} \ No newline at end of file -- 2.47.2 From e5342e34f7106f487e7b3c40b3fcf822e318845a Mon Sep 17 00:00:00 2001 From: bQUARKz Date: Tue, 5 May 2026 13:42:05 +0100 Subject: [PATCH 05/37] added simple README.md on vscode-extension --- tools/vscode-extension/README.md | 155 +++++++++++++++++++++++++++++++ 1 file changed, 155 insertions(+) create mode 100644 tools/vscode-extension/README.md diff --git a/tools/vscode-extension/README.md b/tools/vscode-extension/README.md new file mode 100644 index 00000000..92b247c6 --- /dev/null +++ b/tools/vscode-extension/README.md @@ -0,0 +1,155 @@ +# Prometeu VS Code Extension + +VS Code bridge for Prometeu Studio. + +This extension does **not** start the language server itself. It connects to the Prometeu Studio LSP server running locally. + +```text +VS Code Extension + -> vscode-languageclient + -> TCP 127.0.0.1:7777 + -> Prometeu Studio Java/LSP4J +``` + +## Requirements + +* Node.js +* npm +* VS Code +* Prometeu Studio running with the embedded LSP server enabled + +The Studio LSP server must be listening on: + +```text +127.0.0.1:7777 +``` + +## Install dependencies + +From this directory: + +```bash +npm install +``` + +## Compile + +```bash +npm run compile +``` + +This generates: + +```text +out/extension.js +``` + +## Run in development mode + +Open this extension folder in VS Code: + +```bash +code . +``` + +Press: + +```text +F5 +``` + +This opens a second VS Code window called **Extension Development Host**. + +In that second window, open a Prometeu project and create/open a file like: + +```text +main.pbs +``` + +or: + +```text +main.barrel +``` + +Expected output in: + +```text +View -> Output -> Prometeu LSP +``` + +```text +Prometeu VS Code extension activated. +Connecting to Prometeu Studio LSP at 127.0.0.1:7777... +TCP connection established with Prometeu Studio. +Prometeu Studio LSP client started. +[Info] Hello from Prometeu Studio LSP +``` + +## Run commands manually + +In the Extension Development Host window: + +```text +Cmd+Shift+P +Prometeu: Connect to Studio LSP +``` + +To restart the client: + +```text +Cmd+Shift+P +Prometeu: Restart Studio LSP +``` + +## Package as VSIX + +```bash +npm run compile +vsce package --allow-missing-repository +``` + +This creates a file like: + +```text +prometeu-vscode-extension-0.0.1.vsix +``` + +## Install locally + +```bash +code --install-extension prometeu-vscode-extension-0.0.1.vsix --force +``` + +Then open a Prometeu project normally: + +```bash +code /path/to/prometeu-project +``` + +With Prometeu Studio running, opening `.pbs` or `.barrel` files should activate the extension and connect to the Studio LSP server. + +## Configuration + +Default settings: + +```json +{ + "prometeu.studio.host": "127.0.0.1", + "prometeu.studio.port": 7777 +} +``` + +These can be changed in VS Code settings if needed. + +## Current status + +The extension currently provides only the minimal LSP client bridge: + +* registers `.pbs` +* registers `.barrel` +* connects to Prometeu Studio over TCP +* starts a VS Code `LanguageClient` +* receives LSP messages from the Java/LSP4J server + +The Studio remains the source of trut -- 2.47.2 From b0073cd7bdf9f99ab2696fe8b2cf27e3cd997e87 Mon Sep 17 00:00:00 2001 From: bQUARKz Date: Tue, 5 May 2026 15:50:55 +0100 Subject: [PATCH 06/37] implements PLN-0065 --- discussion/index.ndjson | 3 +- ...0035-studio-new-lsp-api-and-v1-boundary.md | 128 +++++++++ ...0032-studio-new-lsp-api-and-v1-boundary.md | 196 +++++++++++++ ...065-lsp-boundary-and-module-scaffolding.md | 118 ++++++++ ...t-scoped-lsp-server-lifecycle-in-studio.md | 103 +++++++ ...ompiler-backed-dumb-lsp-server-baseline.md | 100 +++++++ gradle/libs.versions.toml | 2 + .../prometeu-lsp-api/build.gradle.kts | 5 +- .../p/studio/lsp/api/LspProjectContext.java | 26 ++ .../studio/lsp/api/LspServerBootRequest.java | 17 ++ .../lsp/api/LspServerConfiguration.java | 29 ++ .../p/studio/lsp/api/LspServerEndpoint.java | 19 ++ .../p/studio/lsp/api/LspServerHandle.java | 13 + .../p/studio/lsp/api/LspServerLifecycle.java | 7 + .../p/studio/lsp/api/LspApiBoundaryTest.java | 32 +++ .../lsp/api/LspServerBootRequestTest.java | 41 +++ prometeu-lsp/prometeu-lsp-v1/build.gradle.kts | 8 +- .../p/studio/lsp/PrometeuStudioLspMain.java | 271 ------------------ .../studio/lsp/v1/PrometeuStudioLspMain.java | 29 ++ .../v1/bootstrap/LspV1ServerLifecycle.java | 64 +++++ .../CompilerLanguageServiceBridge.java | 21 ++ .../v1/host/ProjectScopedLspServerHost.java | 10 + .../ProjectScopedLspServerHostFactory.java | 10 + .../studio/lsp/v1/host/TcpLspServerHost.java | 101 +++++++ .../lsp/v1/host/TcpLspServerHostFactory.java | 13 + .../v1/protocol/PrometeuLanguageServer.java | 101 +++++++ .../protocol/PrometeuTextDocumentService.java | 93 ++++++ .../v1/protocol/PrometeuWorkspaceService.java | 15 + .../mapping/ProtocolServerProfile.java | 11 + .../mapping/ServerCapabilitiesMapper.java | 27 ++ .../bootstrap/LspV1ServerLifecycleTest.java | 63 ++++ .../lsp/v1/boundary/LspV1BoundaryTest.java | 46 +++ 32 files changed, 1445 insertions(+), 277 deletions(-) create mode 100644 discussion/workflow/agendas/AGD-0035-studio-new-lsp-api-and-v1-boundary.md create mode 100644 discussion/workflow/decisions/DEC-0032-studio-new-lsp-api-and-v1-boundary.md create mode 100644 discussion/workflow/plans/PLN-0065-lsp-boundary-and-module-scaffolding.md create mode 100644 discussion/workflow/plans/PLN-0066-project-scoped-lsp-server-lifecycle-in-studio.md create mode 100644 discussion/workflow/plans/PLN-0067-compiler-backed-dumb-lsp-server-baseline.md create mode 100644 prometeu-lsp/prometeu-lsp-api/src/main/java/p/studio/lsp/api/LspProjectContext.java create mode 100644 prometeu-lsp/prometeu-lsp-api/src/main/java/p/studio/lsp/api/LspServerBootRequest.java create mode 100644 prometeu-lsp/prometeu-lsp-api/src/main/java/p/studio/lsp/api/LspServerConfiguration.java create mode 100644 prometeu-lsp/prometeu-lsp-api/src/main/java/p/studio/lsp/api/LspServerEndpoint.java create mode 100644 prometeu-lsp/prometeu-lsp-api/src/main/java/p/studio/lsp/api/LspServerHandle.java create mode 100644 prometeu-lsp/prometeu-lsp-api/src/main/java/p/studio/lsp/api/LspServerLifecycle.java create mode 100644 prometeu-lsp/prometeu-lsp-api/src/test/java/p/studio/lsp/api/LspApiBoundaryTest.java create mode 100644 prometeu-lsp/prometeu-lsp-api/src/test/java/p/studio/lsp/api/LspServerBootRequestTest.java delete mode 100644 prometeu-lsp/prometeu-lsp-v1/src/main/java/p/studio/lsp/PrometeuStudioLspMain.java create mode 100644 prometeu-lsp/prometeu-lsp-v1/src/main/java/p/studio/lsp/v1/PrometeuStudioLspMain.java create mode 100644 prometeu-lsp/prometeu-lsp-v1/src/main/java/p/studio/lsp/v1/bootstrap/LspV1ServerLifecycle.java create mode 100644 prometeu-lsp/prometeu-lsp-v1/src/main/java/p/studio/lsp/v1/compiler/CompilerLanguageServiceBridge.java create mode 100644 prometeu-lsp/prometeu-lsp-v1/src/main/java/p/studio/lsp/v1/host/ProjectScopedLspServerHost.java create mode 100644 prometeu-lsp/prometeu-lsp-v1/src/main/java/p/studio/lsp/v1/host/ProjectScopedLspServerHostFactory.java create mode 100644 prometeu-lsp/prometeu-lsp-v1/src/main/java/p/studio/lsp/v1/host/TcpLspServerHost.java create mode 100644 prometeu-lsp/prometeu-lsp-v1/src/main/java/p/studio/lsp/v1/host/TcpLspServerHostFactory.java create mode 100644 prometeu-lsp/prometeu-lsp-v1/src/main/java/p/studio/lsp/v1/protocol/PrometeuLanguageServer.java create mode 100644 prometeu-lsp/prometeu-lsp-v1/src/main/java/p/studio/lsp/v1/protocol/PrometeuTextDocumentService.java create mode 100644 prometeu-lsp/prometeu-lsp-v1/src/main/java/p/studio/lsp/v1/protocol/PrometeuWorkspaceService.java create mode 100644 prometeu-lsp/prometeu-lsp-v1/src/main/java/p/studio/lsp/v1/protocol/mapping/ProtocolServerProfile.java create mode 100644 prometeu-lsp/prometeu-lsp-v1/src/main/java/p/studio/lsp/v1/protocol/mapping/ServerCapabilitiesMapper.java create mode 100644 prometeu-lsp/prometeu-lsp-v1/src/test/java/p/studio/lsp/v1/bootstrap/LspV1ServerLifecycleTest.java create mode 100644 prometeu-lsp/prometeu-lsp-v1/src/test/java/p/studio/lsp/v1/boundary/LspV1BoundaryTest.java diff --git a/discussion/index.ndjson b/discussion/index.ndjson index 038eb391..a54cea18 100644 --- a/discussion/index.ndjson +++ b/discussion/index.ndjson @@ -1,4 +1,5 @@ -{"type":"meta","next_id":{"DSC":32,"AGD":35,"DEC":32,"PLN":65,"LSN":47,"CLSN":1}} +{"type":"meta","next_id":{"DSC":33,"AGD":36,"DEC":33,"PLN":68,"LSN":47,"CLSN":1}} +{"type":"discussion","id":"DSC-0032","status":"in_progress","ticket":"studio-new-lsp-api-and-v1-boundary","title":"Novo boundary entre lsp-api, lsp-v1 e a extensao VS Code","created_at":"2026-05-05","updated_at":"2026-05-05","tags":["studio","lsp","vscode","protocol","api","boundary"],"agendas":[{"id":"AGD-0035","file":"AGD-0035-studio-new-lsp-api-and-v1-boundary.md","status":"accepted","created_at":"2026-05-05","updated_at":"2026-05-05"}],"decisions":[{"id":"DEC-0032","file":"DEC-0032-studio-new-lsp-api-and-v1-boundary.md","status":"accepted","created_at":"2026-05-05","updated_at":"2026-05-05","ref_agenda":"AGD-0035"}],"plans":[{"id":"PLN-0065","file":"PLN-0065-lsp-boundary-and-module-scaffolding.md","status":"done","created_at":"2026-05-05","updated_at":"2026-05-05","ref_decisions":["DEC-0032"]},{"id":"PLN-0066","file":"PLN-0066-project-scoped-lsp-server-lifecycle-in-studio.md","status":"open","created_at":"2026-05-05","updated_at":"2026-05-05","ref_decisions":["DEC-0032"]},{"id":"PLN-0067","file":"PLN-0067-compiler-backed-dumb-lsp-server-baseline.md","status":"open","created_at":"2026-05-05","updated_at":"2026-05-05","ref_decisions":["DEC-0032"]}],"lessons":[]} {"type":"discussion","id":"DSC-0031","status":"in_progress","ticket":"studio-editor-workspace-cleanup","title":"Limpeza completa do Workspace Editor do Studio e remoção dos acoplamentos legados","created_at":"2026-05-05","updated_at":"2026-05-05","tags":["studio","editor","cleanup","vfs","lsp","migration"],"agendas":[{"id":"AGD-0034","file":"AGD-0034-vscode-editor-migration-feasibility.md","status":"accepted","created_at":"2026-05-05","updated_at":"2026-05-05"}],"decisions":[{"id":"DEC-0031","file":"DEC-0031-studio-editor-workspace-cleanup.md","status":"in_progress","created_at":"2026-05-05","updated_at":"2026-05-05","ref_agenda":"AGD-0034"}],"plans":[{"id":"PLN-0062","file":"PLN-0062-shell-session-and-state-cleanup-after-editor-removal.md","status":"done","created_at":"2026-05-05","updated_at":"2026-05-05","ref_decisions":["DEC-0031"]},{"id":"PLN-0063","file":"PLN-0063-legacy-lsp-and-vfs-module-removal-with-runtime-preservation.md","status":"done","created_at":"2026-05-05","updated_at":"2026-05-05","ref_decisions":["DEC-0031"]},{"id":"PLN-0064","file":"PLN-0064-normative-test-and-lesson-cleanup-for-editor-stack-removal.md","status":"done","created_at":"2026-05-05","updated_at":"2026-05-05","ref_decisions":["DEC-0031"]}],"lessons":[]} {"type":"discussion","id":"DSC-0030","status":"done","ticket":"studio-scene-pack-runtime-binary-contract","title":"Studio scene pack contract for runtime SCENE binary payload","created_at":"2026-04-24","updated_at":"2026-05-01","tags":["studio","packer","runtime","scene","asset-pack","binary-format","tiled"],"agendas":[],"decisions":[],"plans":[],"lessons":[{"id":"LSN-0046","file":"discussion/lessons/DSC-0030-studio-scene-pack-runtime-binary-contract/LSN-0046-canonical-scene-owns-editorial-truth-while-pack-stays-request-driven.md","status":"done","created_at":"2026-05-01","updated_at":"2026-05-01"}]} {"type":"discussion","id":"DSC-0029","status":"done","ticket":"studio-frame-composer-syscall-and-sprite-alignment","title":"Studio Alignment with Runtime FrameComposer Syscalls and Sprite Composition","created_at":"2026-04-18","updated_at":"2026-04-18","tags":["studio","compiler","pbs","stdlib","runtime-alignment","abi","syscall","frame-composer","sprites"],"agendas":[],"decisions":[],"plans":[],"lessons":[{"id":"LSN-0041","file":"discussion/lessons/DSC-0029-studio-frame-composer-syscall-and-sprite-alignment/LSN-0041-composer-must-own-public-sprite-composition.md","status":"done","created_at":"2026-04-18","updated_at":"2026-04-18"}]} diff --git a/discussion/workflow/agendas/AGD-0035-studio-new-lsp-api-and-v1-boundary.md b/discussion/workflow/agendas/AGD-0035-studio-new-lsp-api-and-v1-boundary.md new file mode 100644 index 00000000..cc778e48 --- /dev/null +++ b/discussion/workflow/agendas/AGD-0035-studio-new-lsp-api-and-v1-boundary.md @@ -0,0 +1,128 @@ +--- +id: AGD-0035 +ticket: studio-new-lsp-api-and-v1-boundary +title: Novo boundary entre lsp-api, lsp-v1 e a extensao VS Code +status: accepted +created: 2026-05-05 +resolved: 2026-05-05 +decision: DEC-0032 +tags: [studio, lsp, vscode, protocol, api, boundary] +--- + +## Pain + +O stack legado de editor, `prometeu-lsp` e `prometeu-vfs` acabou de ser removido. O próximo passo natural é reconstruir o backend de linguagem, mas sem repetir o erro anterior de misturar engine semântica, transporte LSP, sessão editorial e host UI em um único desenho. + +Ao mesmo tempo, já existe uma extensão em `tools/vscode-extension` que hoje sabe conectar via TCP em `127.0.0.1:7777` e falar LSP como cliente real. Isso reduz incerteza no lado do FE, mas aumenta a exigência arquitetural do backend: o servidor novo precisa nascer com boundary correto. + +O risco central é reintroduzir acoplamento acidental entre: + +- contratos internos de linguagem; +- transporte externo LSP; +- implementação concreta baseada em `LSP4J`; +- e necessidades específicas do VS Code. + +## Context + +- O cleanup do stack legado foi fechado por `DEC-0031`. +- A extensão VS Code já existe em `tools/vscode-extension`. +- A extensão usa `vscode-languageclient` e conecta por socket TCP configurável. +- O usuário quer explicitamente que `LSP4J` **não vaze** de `lsp-v1`. +- A intenção geral do produto é que o Studio fale a própria língua internamente e exponha adapters externos para FEs, no mesmo espírito já discutido para integrações como Tiled. + +Hoje, a pergunta não é "como implementar o LSP inteiro", mas sim: + +- que módulos recriar; +- qual boundary o `lsp-api` realmente deve carregar; +- e qual responsabilidade cabe a `lsp-v1` como adapter concreto. + +Também já existe um direcionamento adicional do produto: + +- `lsp-v1` deve consumir serviços existentes de `compiler`; +- `lsp-api` deve expor funcionalidades reutilizáveis por outras partes do sistema; +- o bootstrap do servidor deve acontecer quando um projeto é aberto, e o shutdown quando o projeto é fechado; +- a API pode começar mínima, por exemplo com `boot server` e `shutdown server`, e crescer só quando houver necessidade real. + +## Open Questions + +- [x] O `lsp-api` deve expor contratos próprios de domínio/serviço ou DTOs alinhados diretamente ao protocolo LSP? + R: o lsp-api deve expor somente servicos que serao usados por outras partes do sistema, e nao ser um espelho do protocolo. +- [x] O `lsp-v1` deve ser somente um adapter `LSP4J` sobre serviços internos de `compiler`, ou também pode carregar parte da orquestração de sessão? + R: O lsp-v1 deve conter o servidor e todo o necessario para falar LSP, incluindo DTOs e dependencias de LSP4J (e fazer uso de compiler quando necessario). o start e o stop do servidor podem ser chamados via lsp-api, mas a logica de orquestracao de sessao deve ficar dentro do lsp-v1. +- [x] O lifecycle de bootstrap/shutdown do servidor por projeto pertence ao `lsp-api`, ao `lsp-v1`, ou a outro serviço do Studio? + R: o contrato fica no lsp-api, mas a logica de orquestracao fica no lsp-v1. o lsp-api pode expor um contrato como `bootServer(project)` e `shutdownServer(project)`, mas a implementacao concreta e a logica de associar o servidor ao projeto fica no lsp-v1. +- [x] O canal de automação (`compile/build/run/debug`) deve viver fora do novo `lsp-api` desde o início? + R: o canal de automacao deve viver fora do lsp-api. nesse primeiro momento o foco principal deve ser o LSP e o comportamento editorial/semantico. o canal de automacao pode ser discutido e implementado separadamente, sem misturar responsabilidades. +- [x] O `tools/vscode-extension` deve continuar falando LSP puro em socket TCP, ou o produto precisa reservar outra estratégia de transporte já nesta fase? + R: o vscode-extension deve continuar falando LSP puro em socket TCP. o lsp-api deve ser agnóstico ao transporte, mas ainda aceito recomendacoes q sejam mais faceis ou performaticas. + +## Options + +### Option A - `lsp-api` como API diretamente moldada pelo protocolo LSP +- **Approach:** recriar `lsp-api` com tipos e serviços muito próximos da superfície do protocolo, deixando `lsp-v1` apenas como bootstrap `LSP4J` e roteamento para `compiler`. +- **Pro:** acelera integração com o cliente existente e reduz tradução entre camadas. +- **Con:** tende a tornar o protocolo externo dono do desenho interno; muda mal quando surgir outro FE ou outro adapter. +- **Maintainability:** fraca. O risco de vazamento conceitual do protocolo para dentro do domínio é alto, mesmo sem importar classes `LSP4J` fora de `lsp-v1`. + +### Option B - `lsp-api` mínima e operacional; `lsp-v1` como adapter LSP4J que consome `compiler` +- **Approach:** `lsp-api` expõe uma surface mínima e reutilizável para o sistema, começando com operações como `boot server(project)` e `shutdown server(project)` e, no máximo, contratos estáveis que outras partes do Studio precisem enxergar. `lsp-v1` concentra a implementação concreta do servidor, depende exclusivamente de `LSP4J`, e consome os serviços do `compiler` para responder às capacidades LSP. +- **Pro:** respeita a regra de não vazamento de `LSP4J`, evita inflar a API cedo demais e alinha o lifecycle do servidor ao projeto aberto, não ao processo global do Studio. +- **Con:** exige disciplina para não transformar `lsp-api` em um espelho parcial do protocolo nem `lsp-v1` em um segundo backend semântico solto do `compiler`. +- **Maintainability:** forte. O backend nasce hexagonal e o custo de evolução fica mais previsível. + +### Option C - Sem `lsp-api`; expor apenas um servidor LSP concreto em `lsp-v1` +- **Approach:** pular a separação e concentrar tudo em um único módulo novo de servidor, com contratos locais apenas package-private ou internos. +- **Pro:** menor custo inicial de scaffolding. +- **Con:** repete exatamente o tipo de colapso arquitetural que gerou o legado descartado; dificulta teste, substituição de transporte e integração com outros FEs. +- **Maintainability:** ruim. A velocidade inicial é comprada com dívida estrutural imediata. + +## Discussion + +O dado novo mais importante é que o cliente VS Code já está funcional como cliente LSP puro. Isso elimina a necessidade de desenhar o protocolo "pensando no editor". O editor já sabe falar LSP; quem precisa de disciplina agora é o Studio. + +Isso empurra a arquitetura para uma separação bem objetiva: + +- `lsp-api` não deve ser "API pública do protocolo"; +- `lsp-api` deve ser uma API interna e mínima do backend de linguagem do Studio; +- `lsp-v1` deve ser o adapter LSP concreto e consumidor dos serviços de `compiler`; +- `LSP4J` deve existir exclusivamente em `lsp-v1`. + +O ponto sensível é não confundir "API interna" com "engine concreta". Se `lsp-api` virar um lugar para pôr qualquer detalhe de sessão, thread, socket, `CompletableFuture` de transporte, ou estruturas do `LSP4J`, ele já nasce errado. Pelo direcionamento atual, a API deve começar deliberadamente estreita: + +- boot do servidor por projeto; +- shutdown do servidor por projeto; +- e só depois crescer quando outro consumidor real do sistema exigir isso. + +Também vale separar desde já o que não pertence ao LSP: + +- `compile/build/run/debug` não devem entrar no `lsp-api` por conveniência; +- esses fluxos pertencem a um contrato de automação paralelo; +- o LSP deve se limitar ao que é comportamento editorial/semântico. + +Outro ponto: o usuário já fixou que o Studio é o backend autoritativo e o cliente externo é só cliente. Isso reforça que o lifecycle do servidor precisa acompanhar o projeto aberto. Em outras palavras: + +- abrir Studio não implica subir servidor LSP global; +- abrir projeto pode implicar subir o servidor LSP daquele projeto; +- fechar projeto deve encerrar o servidor correspondente. + +As respostas atuais também fecharam um boundary operacional importante: + +- quem "fala LSP" de verdade é o `lsp-v1`; +- `lsp-api` não é adapter nem espelho do protocolo; +- `lsp-api` existe para expor um boundary interno consumível pelo Studio; +- o contrato mínimo inicial pode ser pequeno, desde que suficiente para boot/shutdown por projeto; +- DTOs, tipos e dependências do protocolo podem existir em `lsp-v1` sem contaminar a API interna. + +## Resolution + +Direção recomendada para convergir: + +1. recriar `lsp-api` como surface interna mínima e reutilizável do sistema, começando com bootstrap e shutdown por projeto; +2. recriar `lsp-v1` como adapter LSP/JSON-RPC concreto, com dependência exclusiva de `LSP4J`; +3. fazer `lsp-v1` consumir serviços existentes de `compiler`, em vez de reconstruir pipeline semântico próprio; +4. deixar a lógica concreta de orquestração de sessão e associação `projeto -> servidor` dentro de `lsp-v1`, mesmo quando o bootstrap/shutdown for disparado através de `lsp-api`; +5. tratar qualquer tipo `LSP4J` fora de `lsp-v1` como violação arquitetural; +6. manter `tools/vscode-extension` como cliente LSP puro em socket TCP; +7. discutir separadamente o contrato de automação para `compile/build/run/debug`, em vez de empurrá-lo para dentro do LSP. + +Neste ponto, a agenda já tem direção clara o bastante para virar `decision`. O que ainda resta fechar depois disso é implementação, não escolha arquitetural principal. diff --git a/discussion/workflow/decisions/DEC-0032-studio-new-lsp-api-and-v1-boundary.md b/discussion/workflow/decisions/DEC-0032-studio-new-lsp-api-and-v1-boundary.md new file mode 100644 index 00000000..d3d19bcc --- /dev/null +++ b/discussion/workflow/decisions/DEC-0032-studio-new-lsp-api-and-v1-boundary.md @@ -0,0 +1,196 @@ +--- +id: DEC-0032 +ticket: studio-new-lsp-api-and-v1-boundary +title: Boundary normativo entre lsp-api, lsp-v1 e a extensao VS Code +status: accepted +created: 2026-05-05 +accepted: 2026-05-05 +agenda: AGD-0035 +plans: [PLN-0065, PLN-0066, PLN-0067] +tags: [studio, lsp, vscode, protocol, api, boundary, compiler] +--- + +## Decision + +O repositório SHALL reconstruir o stack de linguagem do Studio com separação explícita entre: + +1. `lsp-api` como boundary interno do Studio; +2. `lsp-v1` como adapter LSP/JSON-RPC concreto; +3. `compiler` como owner dos serviços semânticos e de análise consumidos por esse adapter; +4. `tools/vscode-extension` como cliente externo que continua falando LSP puro via socket TCP. + +Esta decisão ALSO locks os seguintes pontos: + +1. `lsp-api` MUST NOT ser espelho do protocolo LSP; +2. `lsp-api` MUST expor apenas funcionalidades internas realmente consumíveis por outras partes do Studio; +3. `lsp-api` MAY começar mínima, por exemplo com contratos como `bootServer(project)` e `shutdownServer(project)`; +4. `lsp-v1` MUST concentrar o servidor LSP concreto, os DTOs de protocolo, o transporte e qualquer dependência de `LSP4J`; +5. `LSP4J` MUST NOT vazar para fora de `lsp-v1`; +6. `lsp-v1` MUST consumir serviços existentes de `compiler` em vez de reconstruir pipeline semântico próprio; +7. o lifecycle do servidor LSP MUST ser associado à abertura e ao fechamento de projeto, não à abertura global do processo Studio; +8. o atual `lsp-v1` presente hoje no repositório serve apenas como mock de conectividade VS Code ↔ Studio e MUST NOT ser tratado como padrão arquitetural, base estrutural ou referência de implementação do backend definitivo. +9. a primeira onda de implementação desta decisão SHALL priorizar arquitetura, lifecycle e separação de responsabilidades, mesmo que o comportamento LSP permaneça deliberadamente simples ou "dumb" por um período controlado. + +## Rationale + +O stack legado anterior foi removido justamente porque misturava responsabilidades erradas e criou boundaries frágeis entre UI, sessão, semântica e transporte. + +Ao mesmo tempo, o projeto já tem dois fatos importantes: + +1. a extensão VS Code já existe e já sabe atuar como cliente LSP puro; +2. o Studio já possui serviços de `compiler` que devem continuar sendo a fonte real de comportamento semântico. + +Logo, o problema não é "inventar um cliente" nem "reescrever a semântica". O problema é definir corretamente: + +1. o que é boundary interno reutilizável do Studio; +2. o que é adapter concreto de protocolo; +3. e onde termina a influência do protocolo externo. + +Essa separação reduz acoplamento, melhora teste e evita que detalhes de `LSP4J` ou do transporte contaminem o restante da base. + +Também existe uma prioridade explícita de rollout: + +1. primeiro consolidar a arquitetura; +2. depois adicionar capacidade semântica por camadas; +3. sem obrigar a primeira implementação a já ser semanticamente rica. + +Isso evita repetir o padrão anterior de crescer funcionalidade em cima de uma base estrutural errada. + +## Technical Specification + +### 1. Module Roles + +`lsp-api` MUST ser tratado como módulo de boundary interno do Studio. + +Ele SHALL: + +1. expor somente contratos que façam sentido para outros consumidores internos do sistema; +2. permanecer agnóstico ao protocolo LSP concreto; +3. permanecer agnóstico a `LSP4J`; +4. permanecer agnóstico ao transporte TCP ou a qualquer detalhe de socket; +5. começar com surface mínima suficiente para o lifecycle do servidor por projeto. + +`lsp-v1` MUST ser tratado como o primeiro adapter concreto do boundary acima. + +Ele SHALL: + +1. implementar o servidor LSP; +2. carregar os DTOs e tipos de protocolo que forem necessários para falar LSP; +3. carregar a dependência de `LSP4J`; +4. realizar a tradução entre o mundo do protocolo e os serviços internos consumidos; +5. concentrar a lógica concreta de sessão e associação `projeto -> servidor`. + +### 2. LSP4J Containment + +O repositório MUST tratar `LSP4J` como dependência exclusiva de `lsp-v1`. + +Portanto: + +1. nenhum tipo de `LSP4J` MAY aparecer em `lsp-api`; +2. nenhum tipo de `LSP4J` MAY aparecer em outros módulos do Studio; +3. nenhum contrato de `lsp-api` MAY depender semanticamente de tipos, nomes ou formas obrigadas pelo `LSP4J`; +4. qualquer vazamento de `LSP4J` para fora de `lsp-v1` SHALL ser tratado como violação arquitetural. + +### 3. Compiler Ownership + +`lsp-v1` MUST consumir serviços existentes de `compiler` quando precisar responder capacidades editoriais e semânticas. + +Isso implica: + +1. `lsp-v1` MUST NOT reconstruir uma engine semântica paralela por conveniência; +2. `lsp-v1` MUST preferir compor sobre entrypoints e serviços canônicos do `compiler`; +3. qualquer lacuna percebida no `compiler` para servir o novo backend SHALL ser tratada como evolução explícita do `compiler`, e não como autorização para duplicação semântica dentro de `lsp-v1`. + +### 4. Server Lifecycle + +O lifecycle do servidor MUST ser project-scoped. + +Regras: + +1. abrir o processo Studio MUST NOT implicitamente significar "subir um servidor LSP global"; +2. abrir um projeto MAY disparar `bootServer(project)` através do boundary exposto por `lsp-api`; +3. fechar um projeto MUST disparar `shutdownServer(project)` para o servidor correspondente; +4. a implementação concreta desse bootstrap/shutdown e o vínculo entre projeto e instância do servidor MUST residir em `lsp-v1`. + +### 5. Internal API Minimalism + +`lsp-api` MUST nascer pequeno. + +Ele SHALL: + +1. expor apenas o que outro consumidor interno realmente precise enxergar; +2. evitar DTOs de protocolo sem necessidade; +3. evitar antecipar capacidades futuras sem consumidor real; +4. crescer somente quando houver pressão concreta de uso interno. + +O contrato inicial mínimo aceito por esta decisão é: + +1. `bootServer(project)` +2. `shutdownServer(project)` + +Contratos adicionais MAY ser adicionados depois, mas não fazem parte do lock inicial desta decisão. + +### 6. VS Code Transport + +`tools/vscode-extension` SHALL permanecer cliente LSP puro via socket TCP nesta fase. + +Isso implica: + +1. a extensão atual pode continuar evoluindo nesse modelo; +2. `lsp-api` MUST permanecer agnóstico a esse transporte; +3. mudanças futuras de transporte MAY ser discutidas depois, mas não fazem parte do boundary normativo inicial. + +### 7. Current Mock Status + +O `lsp-v1` que existe hoje para testes de conectividade entre VS Code e Studio MUST ser tratado como mock transitório. + +Ele MUST NOT: + +1. servir de blueprint estrutural do novo servidor; +2. servir de contrato implícito do sistema; +3. servir de justificativa para manter responsabilidades colapsadas; +4. contaminar o padrão de código alvo do backend definitivo. + +O backend definitivo SHALL priorizar: + +1. separação clara de responsabilidades; +2. boundaries pequenos e explícitos; +3. código fácil de manter; +4. composição sobre serviços canônicos do `compiler`; +5. isolamento rígido do adapter de protocolo. + +### 8. Implementation Wave 1 + +A primeira onda de implementação derivada desta decisão MUST focar em transformar o mock atual em uma estrutura sólida de trabalho. + +Essa onda SHALL incluir: + +1. `lsp-api` mínimo com bootstrap e shutdown por projeto; +2. `lsp-v1` organizado como adapter concreto limpo, mesmo que ainda responda um conjunto reduzido ou simplificado de capacidades; +3. boot do servidor quando o projeto abrir; +4. shutdown do servidor quando o projeto fechar; +5. isolamento explícito entre boundary interno, adapter de protocolo e consumo de `compiler`. + +Essa onda MUST NOT ser bloqueada pela ausência de "carne semântica" completa. + +Em outras palavras: + +1. é aceitável manter um comportamento LSP inicial deliberadamente simples; +2. não é aceitável manter um padrão arquitetural improvisado só porque o comportamento ainda é simples; +3. a evolução semântica futura SHALL acontecer por camadas sobre a estrutura consolidada. + +## Constraints + +1. Esta decisão MUST preservar a separação entre boundary interno e adapter externo. +2. Esta decisão MUST preservar `compiler` como owner semântico do sistema. +3. Esta decisão MUST impedir vazamento de `LSP4J` para fora de `lsp-v1`. +4. Esta decisão MUST impedir que o mock atual de conectividade seja usado como padrão do produto. +5. Esta decisão MUST manter `compile/build/run/debug` fora do escopo do `lsp-api` nesta fase. +6. Qualquer plano derivado desta decisão MUST refletir explicitamente o lifecycle por projeto e a contenção de protocolo em `lsp-v1`. +7. O primeiro plano derivado desta decisão MUST priorizar a consolidação estrutural do servidor antes do enriquecimento semântico. + +## Revision Log + +- 2026-05-05: Initial draft from AGD-0035. +- 2026-05-05: Added explicit phase-1 rollout guidance to solidify architecture before semantic depth. +- 2026-05-05: Accepted and decomposed into PLN-0065, PLN-0066, and PLN-0067. diff --git a/discussion/workflow/plans/PLN-0065-lsp-boundary-and-module-scaffolding.md b/discussion/workflow/plans/PLN-0065-lsp-boundary-and-module-scaffolding.md new file mode 100644 index 00000000..0783cf6c --- /dev/null +++ b/discussion/workflow/plans/PLN-0065-lsp-boundary-and-module-scaffolding.md @@ -0,0 +1,118 @@ +--- +id: PLN-0065 +ticket: studio-new-lsp-api-and-v1-boundary +title: LSP Boundary and Module Scaffolding +status: done +created: 2026-05-05 +completed: 2026-05-05 +tags: [studio, lsp, api, boundary, modules, architecture] +--- + +## Objective + +Recreate `prometeu-lsp:prometeu-lsp-api` and `prometeu-lsp:prometeu-lsp-v1` with a structurally correct boundary that is ready for long-term maintenance, while intentionally keeping the initial server behavior minimal. + +## Background + +`DEC-0032` locks that: + +- `lsp-api` is an internal Studio boundary, not a mirror of the LSP protocol; +- `lsp-v1` is the concrete LSP adapter and the only module allowed to depend on `LSP4J`; +- the current mock server shape MUST NOT be treated as the product pattern; +- wave 1 prioritizes architecture and lifecycle over semantic depth. + +The repository already reserves `prometeu-lsp:*` in `settings.gradle.kts`, but the modules are currently empty shells after the cleanup. + +## Scope + +### Included +- Recreate Gradle/module structure for `prometeu-lsp-api` and `prometeu-lsp-v1`. +- Define the minimal internal API contract for server lifecycle by project. +- Establish package boundaries that keep protocol DTOs and `LSP4J` types out of `lsp-api`. +- Add boundary-oriented tests or build checks where feasible. + +### Excluded +- Wiring the server into Studio project open/close. +- Rich semantic behavior, diagnostics, definition, symbols, or incremental analysis. +- Automation channel work for `compile/build/run/debug`. + +## Non-Goals + +- Full language feature implementation. +- Any attempt to preserve compatibility with the legacy removed `prometeu-lsp`. +- Transport changes in the VS Code extension. + +## Execution Steps + +### Step 1 - Recreate the Gradle modules with explicit dependency ownership + +**What:** Reintroduce the `prometeu-lsp-api` and `prometeu-lsp-v1` modules as clean boundaries. +**How:** Restore the module directories and `build.gradle.kts` files, wire them in `settings.gradle.kts`, and keep dependencies explicit: + +- `prometeu-lsp-api` depends only on stable internal modules it truly needs; +- `prometeu-lsp-v1` depends on `prometeu-lsp-api`, `compiler` services it consumes, and `LSP4J`; +- no other Studio module depends on `LSP4J`. + +**File(s):** `settings.gradle.kts`, `prometeu-lsp/prometeu-lsp-api/build.gradle.kts`, `prometeu-lsp/prometeu-lsp-v1/build.gradle.kts`, affected root/module build files. + +### Step 2 - Define the minimal internal lifecycle contract in `lsp-api` + +**What:** Create the smallest stable API needed by the Studio host. +**How:** Add internal contracts such as a project-scoped `bootServer(project)` and `shutdownServer(project)` surface plus the minimal supporting DTO/entity types required by that lifecycle. Keep the API transport-agnostic and free of protocol DTOs. +**File(s):** `prometeu-lsp/prometeu-lsp-api/src/main/java/**`. + +### Step 3 - Define the adapter shape in `lsp-v1` + +**What:** Establish the internal code organization of the concrete adapter. +**How:** Create clear package slices inside `lsp-v1`, such as: + +- lifecycle/bootstrap, +- server host/transport, +- protocol DTO mapping, +- compiler-facing service bridge. + +The implementation may stay behaviorally dumb, but the structure MUST already reflect the final responsibility split. +**File(s):** `prometeu-lsp/prometeu-lsp-v1/src/main/java/**`. + +### Step 4 - Add boundary conformance tests + +**What:** Prevent architectural drift from day 1. +**How:** Add tests or static checks that fail if: + +- `lsp-api` imports `LSP4J`; +- protocol DTOs leak into `lsp-api`; +- non-`lsp-v1` Studio modules start importing `LSP4J`. + +**File(s):** `prometeu-lsp/prometeu-lsp-api/src/test/java/**`, `prometeu-lsp/prometeu-lsp-v1/src/test/java/**`, or build-level checks if that is cleaner. + +## Test Requirements + +### Unit Tests +- Verify the lifecycle contracts in `lsp-api` have deterministic defaults and null-safety. +- Verify `lsp-v1` module-local bootstrap pieces can be instantiated without a running Studio shell. +- Verify boundary checks catch `LSP4J` leakage. + +### Integration Tests +- Run a root or targeted Gradle build proving the new modules compile and coexist with `prometeu-studio` and `prometeu-app`. + +### Manual Verification +- Inspect the recreated module tree and confirm `lsp-api` contains no protocol or `LSP4J` types. + +## Acceptance Criteria + +- [x] `prometeu-lsp-api` and `prometeu-lsp-v1` exist again as active modules. +- [x] `lsp-api` exposes only internal lifecycle-oriented contracts. +- [x] `lsp-v1` is the only module allowed to depend on `LSP4J`. +- [x] The new module structure expresses clear responsibility boundaries even with dumb behavior. +- [x] Boundary conformance is covered by tests or equivalent build checks. + +## Dependencies + +- `DEC-0032` accepted and normatively locked. +- Current Gradle graph and module includes available for reactivation. + +## Risks + +- Reintroducing the modules too loosely can recreate the same ambiguity that killed the legacy stack. +- An underspecified API can force churn later; an oversized API can lock the wrong shape too early. +- Build-only enforcement may miss architectural drift unless the checks are explicit. diff --git a/discussion/workflow/plans/PLN-0066-project-scoped-lsp-server-lifecycle-in-studio.md b/discussion/workflow/plans/PLN-0066-project-scoped-lsp-server-lifecycle-in-studio.md new file mode 100644 index 00000000..c6144269 --- /dev/null +++ b/discussion/workflow/plans/PLN-0066-project-scoped-lsp-server-lifecycle-in-studio.md @@ -0,0 +1,103 @@ +--- +id: PLN-0066 +ticket: studio-new-lsp-api-and-v1-boundary +title: Project-Scoped LSP Server Lifecycle in Studio +status: open +created: 2026-05-05 +completed: +tags: [studio, lsp, lifecycle, projects, boot, shutdown] +--- + +## Objective + +Wire the new LSP server lifecycle into the Studio project lifecycle so a server starts when a project opens and stops when that project closes, without introducing a process-global LSP service. + +## Background + +`DEC-0032` requires a project-scoped server lifecycle and explicitly rejects a global Studio-wide server. The current natural integration points are: + +- `StudioProjectSession` +- `StudioProjectSessionFactory` +- `StudioWindowCoordinator` + +These surfaces already own project startup and teardown flow and therefore are the correct place to consume `lsp-api`. + +## Scope + +### Included +- Add project-scoped LSP server ownership to the Studio project session lifecycle. +- Boot the server during project open. +- Shutdown the server during project close. +- Preserve existing shell, packer, play/stop, and debug flows. + +### Excluded +- Rich semantic responses. +- Automation channel work. +- VS Code extension transport changes. + +## Non-Goals + +- Cross-project shared server process management. +- Multi-project pooling or server reuse. +- Changing the overall launcher/window model. + +## Execution Steps + +### Step 1 - Extend project session ownership to include the LSP lifecycle boundary + +**What:** Make `StudioProjectSession` own the new project-scoped LSP service reference. +**How:** Add the minimal `lsp-api` contract to `StudioProjectSession`, ensure it is initialized by `StudioProjectSessionFactory`, and guarantee shutdown on `close()`, including failure-safe teardown ordering. +**File(s):** `prometeu-studio/src/main/java/p/studio/projectsessions/StudioProjectSession.java`, `prometeu-studio/src/main/java/p/studio/projectsessions/StudioProjectSessionFactory.java`, related tests. + +### Step 2 - Trigger boot during project open flow + +**What:** Start the LSP server as part of project initialization. +**How:** Update the project-open sequence so the server boots after the project context is ready and before the project window is considered fully opened. Ensure failures surface as project-open failures instead of becoming silent background errors. +**File(s):** `prometeu-studio/src/main/java/p/studio/window/StudioWindowCoordinator.java`, possibly `prometeu-app/src/main/java/p/studio/AppContainer.java` and `prometeu-studio/src/main/java/p/studio/Container.java` if dependency injection changes are needed. + +### Step 3 - Trigger shutdown during project close flow + +**What:** Cleanly stop the project-bound server when the project closes. +**How:** Ensure the existing project close path tears down the LSP service through the session close path, with no leaked socket listener or hanging background resources. +**File(s):** `prometeu-studio/src/main/java/p/studio/window/StudioWindowCoordinator.java`, `prometeu-studio/src/main/java/p/studio/projectsessions/StudioProjectSession.java`. + +### Step 4 - Preserve current dumb connectivity semantics + +**What:** Keep the initial server behavior intentionally simple while validating lifecycle. +**How:** Wire the server so the VS Code extension can still connect over TCP, even if the server behavior remains a minimal handshake or stubbed capability set for now. +**File(s):** `prometeu-lsp/prometeu-lsp-v1/src/main/java/**`, `tools/vscode-extension/src/extension.ts` only if configuration or expectations need adjustment. + +## Test Requirements + +### Unit Tests +- Verify project session close calls LSP shutdown exactly once. +- Verify boot failures are surfaced deterministically during project open. +- Verify repeated close remains idempotent. + +### Integration Tests +- Run `prometeu-studio` tests covering project open/close lifecycle. +- Add a focused integration test proving a project-scoped server is booted and then shut down. + +### Manual Verification +- Open a Studio project, confirm the server starts. +- Close the project, confirm the server port is released and the process/resources terminate. +- Connect via the existing VS Code extension and confirm the dumb server remains reachable. + +## Acceptance Criteria + +- [ ] Opening a Studio project boots an LSP server for that project. +- [ ] Closing the project shuts down that server. +- [ ] The lifecycle is owned by project session boundaries, not global app startup. +- [ ] Existing non-LSP project flows remain operational. +- [ ] The current dumb connectivity workflow remains usable as a temporary implementation phase. + +## Dependencies + +- `DEC-0032` accepted and normatively locked. +- `PLN-0065` providing the new module and API boundary. + +## Risks + +- Startup ordering mistakes can make project open flaky or hide boot errors. +- Shutdown ordering mistakes can leak ports or threads. +- Lifecycle wiring can accidentally reintroduce global process ownership if the session boundary is not kept strict. diff --git a/discussion/workflow/plans/PLN-0067-compiler-backed-dumb-lsp-server-baseline.md b/discussion/workflow/plans/PLN-0067-compiler-backed-dumb-lsp-server-baseline.md new file mode 100644 index 00000000..d320f1f8 --- /dev/null +++ b/discussion/workflow/plans/PLN-0067-compiler-backed-dumb-lsp-server-baseline.md @@ -0,0 +1,100 @@ +--- +id: PLN-0067 +ticket: studio-new-lsp-api-and-v1-boundary +title: Compiler-Backed Dumb LSP Server Baseline +status: open +created: 2026-05-05 +completed: +tags: [studio, lsp, compiler, baseline, protocol, vscode] +--- + +## Objective + +Establish a maintainable, compiler-backed baseline inside `lsp-v1` that keeps the server behavior deliberately simple while creating the seams required for later semantic layering. + +## Background + +`DEC-0032` explicitly allows wave 1 to remain semantically thin, but it forbids keeping an ad hoc mock structure as the long-term coding pattern. The backend therefore needs a baseline that is: + +- dumb in behavior when necessary, +- but already correctly composed over `compiler` services, +- and already structured for layered enrichment later. + +## Scope + +### Included +- Create compiler-facing service seams used by `lsp-v1`. +- Provide a small, explicit set of LSP capabilities or responses that prove the adapter shape. +- Keep the VS Code extension compatible with the current TCP model. +- Document the temporary behavioral limits in code and tests. + +### Excluded +- Full diagnostics, definition, symbols, inlay hints, or multi-file semantic completeness. +- Automation channel work. +- Non-TCP transport experiments. + +## Non-Goals + +- Matching the full final language feature set. +- Recreating the deleted legacy `prometeu-lsp` behavior. +- Optimizing for performance before the baseline structure is validated. + +## Execution Steps + +### Step 1 - Define compiler-facing bridge services inside `lsp-v1` + +**What:** Introduce explicit bridge classes or adapters between protocol handlers and `compiler`. +**How:** Create narrow services inside `lsp-v1` that own calls into `compiler` entrypoints. Even if the first concrete responses are stubbed or partial, the protocol handlers must already call through these seams instead of embedding compiler knowledge everywhere. +**File(s):** `prometeu-lsp/prometeu-lsp-v1/src/main/java/**`, relevant `prometeu-compiler` integration points when discoverable. + +### Step 2 - Implement a minimal but structured capability slice + +**What:** Keep the server intentionally dumb, but no longer structurally improvised. +**How:** Choose a small capability surface such as `initialize`, `shutdown`, and one lightweight language feature or health response. The exact feature set may stay narrow, but the code must already follow the final layering: + +- protocol request handling, +- bridge service invocation, +- result mapping. + +**File(s):** `prometeu-lsp/prometeu-lsp-v1/src/main/java/**`, potentially `tools/vscode-extension/src/extension.ts` if initialization expectations need tightening. + +### Step 3 - Codify temporary behavior limits + +**What:** Make the current limitations explicit instead of implicit. +**How:** Add tests and lightweight documentation/comments that define the intentionally supported baseline behavior so future work can add capability in layers without guessing what the "mock" currently means. +**File(s):** `prometeu-lsp/prometeu-lsp-v1/src/test/java/**`, targeted source comments where they reduce ambiguity. + +## Test Requirements + +### Unit Tests +- Verify protocol handlers call the correct bridge services. +- Verify compiler bridge services can be instantiated and return stable baseline results. +- Verify no handler bypasses the bridge layer to embed semantic logic ad hoc. + +### Integration Tests +- Run a targeted Studio/LSP integration proving the VS Code client can initialize against the dumb server. +- Run compiler-related tests needed to validate the consumed service seams. + +### Manual Verification +- Connect from VS Code and confirm the server initializes and remains stable. +- Confirm the limited capability set behaves predictably and does not masquerade as richer support than actually implemented. + +## Acceptance Criteria + +- [ ] `lsp-v1` talks to `compiler` through explicit bridge services. +- [ ] The baseline server behavior remains intentionally simple but structurally clean. +- [ ] At least one minimal end-to-end capability slice proves the final layering. +- [ ] The extension can still connect over TCP without protocol regressions. +- [ ] Temporary semantic limits are explicit in tests and code structure. + +## Dependencies + +- `DEC-0032` accepted and normatively locked. +- `PLN-0065` for module/boundary setup. +- `PLN-0066` for project-scoped lifecycle integration. + +## Risks + +- A "temporary" dumb server can calcify unless the seams are truly explicit and tested. +- Over-stubbing can hide compiler integration issues that should be surfaced early. +- Picking too many baseline features in this wave can dilute the architectural focus. diff --git a/gradle/libs.versions.toml b/gradle/libs.versions.toml index 84d8cc26..8324a30f 100644 --- a/gradle/libs.versions.toml +++ b/gradle/libs.versions.toml @@ -6,6 +6,7 @@ jacoco = "0.8.12" lombok = "1.18.32" junit-jupiter = "5.12.1" slf4j = "2.0.7" +lsp4j = "1.0.0" [libraries] javafx-controls = { group = "org.openjfx", name = "javafx-controls", version.ref = "javafx" } @@ -20,6 +21,7 @@ lombok = { group = "org.projectlombok", name = "lombok", version.ref = "lombok" junit-jupiter = { group = "org.junit.jupiter", name = "junit-jupiter", version.ref = "junit-jupiter" } slf4j-api = { group = "org.slf4j", name = "slf4j-api", version.ref = "slf4j" } slf4j-simple = { group = "org.slf4j", name = "slf4j-simple", version.ref = "slf4j" } +lsp4j = { group = "org.eclipse.lsp4j", name = "org.eclipse.lsp4j", version.ref = "lsp4j" } [plugins] javafx = { id = "org.openjfx.javafxplugin", version = "0.1.0" } diff --git a/prometeu-lsp/prometeu-lsp-api/build.gradle.kts b/prometeu-lsp/prometeu-lsp-api/build.gradle.kts index 5c470d4e..ef87e22b 100644 --- a/prometeu-lsp/prometeu-lsp-api/build.gradle.kts +++ b/prometeu-lsp/prometeu-lsp-api/build.gradle.kts @@ -1,3 +1,6 @@ plugins { id("gradle.java-library-conventions") -} \ No newline at end of file +} + +dependencies { +} diff --git a/prometeu-lsp/prometeu-lsp-api/src/main/java/p/studio/lsp/api/LspProjectContext.java b/prometeu-lsp/prometeu-lsp-api/src/main/java/p/studio/lsp/api/LspProjectContext.java new file mode 100644 index 00000000..02b9f8da --- /dev/null +++ b/prometeu-lsp/prometeu-lsp-api/src/main/java/p/studio/lsp/api/LspProjectContext.java @@ -0,0 +1,26 @@ +package p.studio.lsp.api; + +import java.nio.file.Path; +import java.util.Objects; + +public record LspProjectContext( + String projectKey, + String languageId, + Path projectRoot) { + + public LspProjectContext { + projectKey = requireText(projectKey, "projectKey"); + languageId = requireText(languageId, "languageId"); + projectRoot = Objects.requireNonNull(projectRoot, "projectRoot").toAbsolutePath().normalize(); + } + + private static String requireText( + final String value, + final String field) { + final String candidate = Objects.requireNonNull(value, field).trim(); + if (candidate.isEmpty()) { + throw new IllegalArgumentException(field + " must not be blank"); + } + return candidate; + } +} diff --git a/prometeu-lsp/prometeu-lsp-api/src/main/java/p/studio/lsp/api/LspServerBootRequest.java b/prometeu-lsp/prometeu-lsp-api/src/main/java/p/studio/lsp/api/LspServerBootRequest.java new file mode 100644 index 00000000..2406a24f --- /dev/null +++ b/prometeu-lsp/prometeu-lsp-api/src/main/java/p/studio/lsp/api/LspServerBootRequest.java @@ -0,0 +1,17 @@ +package p.studio.lsp.api; + +import java.util.Objects; + +public record LspServerBootRequest( + LspProjectContext project, + LspServerConfiguration configuration) { + + public LspServerBootRequest { + project = Objects.requireNonNull(project, "project"); + configuration = Objects.requireNonNull(configuration, "configuration"); + } + + public static LspServerBootRequest defaults(final LspProjectContext project) { + return new LspServerBootRequest(project, LspServerConfiguration.defaults()); + } +} diff --git a/prometeu-lsp/prometeu-lsp-api/src/main/java/p/studio/lsp/api/LspServerConfiguration.java b/prometeu-lsp/prometeu-lsp-api/src/main/java/p/studio/lsp/api/LspServerConfiguration.java new file mode 100644 index 00000000..f5f8644a --- /dev/null +++ b/prometeu-lsp/prometeu-lsp-api/src/main/java/p/studio/lsp/api/LspServerConfiguration.java @@ -0,0 +1,29 @@ +package p.studio.lsp.api; + +import java.util.Objects; + +public record LspServerConfiguration( + String host, + int port) { + public static final String DEFAULT_HOST = "127.0.0.1"; + public static final int DEFAULT_PORT = 7777; + + public LspServerConfiguration { + host = requireHost(host); + if (port < 0 || port > 65535) { + throw new IllegalArgumentException("port must be between 0 and 65535"); + } + } + + public static LspServerConfiguration defaults() { + return new LspServerConfiguration(DEFAULT_HOST, DEFAULT_PORT); + } + + private static String requireHost(final String value) { + final String candidate = Objects.requireNonNull(value, "host").trim(); + if (candidate.isEmpty()) { + throw new IllegalArgumentException("host must not be blank"); + } + return candidate; + } +} diff --git a/prometeu-lsp/prometeu-lsp-api/src/main/java/p/studio/lsp/api/LspServerEndpoint.java b/prometeu-lsp/prometeu-lsp-api/src/main/java/p/studio/lsp/api/LspServerEndpoint.java new file mode 100644 index 00000000..db255c1f --- /dev/null +++ b/prometeu-lsp/prometeu-lsp-api/src/main/java/p/studio/lsp/api/LspServerEndpoint.java @@ -0,0 +1,19 @@ +package p.studio.lsp.api; + +import java.util.Objects; + +public record LspServerEndpoint( + String host, + int port) { + + public LspServerEndpoint { + final String candidate = Objects.requireNonNull(host, "host").trim(); + if (candidate.isEmpty()) { + throw new IllegalArgumentException("host must not be blank"); + } + if (port < 0 || port > 65535) { + throw new IllegalArgumentException("port must be between 0 and 65535"); + } + host = candidate; + } +} diff --git a/prometeu-lsp/prometeu-lsp-api/src/main/java/p/studio/lsp/api/LspServerHandle.java b/prometeu-lsp/prometeu-lsp-api/src/main/java/p/studio/lsp/api/LspServerHandle.java new file mode 100644 index 00000000..9c90d38f --- /dev/null +++ b/prometeu-lsp/prometeu-lsp-api/src/main/java/p/studio/lsp/api/LspServerHandle.java @@ -0,0 +1,13 @@ +package p.studio.lsp.api; + +import java.util.Objects; + +public record LspServerHandle( + LspProjectContext project, + LspServerEndpoint endpoint) { + + public LspServerHandle { + project = Objects.requireNonNull(project, "project"); + endpoint = Objects.requireNonNull(endpoint, "endpoint"); + } +} diff --git a/prometeu-lsp/prometeu-lsp-api/src/main/java/p/studio/lsp/api/LspServerLifecycle.java b/prometeu-lsp/prometeu-lsp-api/src/main/java/p/studio/lsp/api/LspServerLifecycle.java new file mode 100644 index 00000000..24863daa --- /dev/null +++ b/prometeu-lsp/prometeu-lsp-api/src/main/java/p/studio/lsp/api/LspServerLifecycle.java @@ -0,0 +1,7 @@ +package p.studio.lsp.api; + +public interface LspServerLifecycle { + LspServerHandle bootServer(LspServerBootRequest request); + + void shutdownServer(LspProjectContext project); +} diff --git a/prometeu-lsp/prometeu-lsp-api/src/test/java/p/studio/lsp/api/LspApiBoundaryTest.java b/prometeu-lsp/prometeu-lsp-api/src/test/java/p/studio/lsp/api/LspApiBoundaryTest.java new file mode 100644 index 00000000..055b151c --- /dev/null +++ b/prometeu-lsp/prometeu-lsp-api/src/test/java/p/studio/lsp/api/LspApiBoundaryTest.java @@ -0,0 +1,32 @@ +package p.studio.lsp.api; + +import org.junit.jupiter.api.Test; + +import java.io.IOException; +import java.nio.file.Files; +import java.nio.file.Path; +import java.util.List; + +import static org.junit.jupiter.api.Assertions.assertTrue; + +class LspApiBoundaryTest { + + @Test + void apiSourceMustRemainFreeOfLsp4jAndProtocolPackages() throws IOException { + final Path sourceRoot = Path.of("src/main/java"); + final List javaFiles; + try (var stream = Files.walk(sourceRoot)) { + javaFiles = stream + .filter(path -> path.toString().endsWith(".java")) + .toList(); + } + + for (final Path javaFile : javaFiles) { + final String source = Files.readString(javaFile); + assertTrue(!source.contains("org.eclipse.lsp4j"), + () -> "LSP4J leaked into lsp-api: " + javaFile); + assertTrue(!source.contains(".protocol."), + () -> "Protocol package leaked into lsp-api: " + javaFile); + } + } +} diff --git a/prometeu-lsp/prometeu-lsp-api/src/test/java/p/studio/lsp/api/LspServerBootRequestTest.java b/prometeu-lsp/prometeu-lsp-api/src/test/java/p/studio/lsp/api/LspServerBootRequestTest.java new file mode 100644 index 00000000..bd895b74 --- /dev/null +++ b/prometeu-lsp/prometeu-lsp-api/src/test/java/p/studio/lsp/api/LspServerBootRequestTest.java @@ -0,0 +1,41 @@ +package p.studio.lsp.api; + +import org.junit.jupiter.api.Test; + +import java.nio.file.Path; + +import static org.junit.jupiter.api.Assertions.assertEquals; +import static org.junit.jupiter.api.Assertions.assertThrows; + +class LspServerBootRequestTest { + + @Test + void defaultsUseDeterministicLoopbackConfiguration() { + final LspProjectContext project = new LspProjectContext("demo", "pbs", Path.of(".")); + + final LspServerBootRequest request = LspServerBootRequest.defaults(project); + + assertEquals(project, request.project()); + assertEquals(LspServerConfiguration.DEFAULT_HOST, request.configuration().host()); + assertEquals(LspServerConfiguration.DEFAULT_PORT, request.configuration().port()); + } + + @Test + void configurationRejectsInvalidValues() { + assertThrows(NullPointerException.class, () -> new LspServerConfiguration(null, 7777)); + assertThrows(IllegalArgumentException.class, () -> new LspServerConfiguration(" ", 7777)); + assertThrows(IllegalArgumentException.class, () -> new LspServerConfiguration("127.0.0.1", -1)); + } + + @Test + void projectContextNormalizesAndRejectsBlankFields() { + final LspProjectContext context = new LspProjectContext(" demo ", " pbs ", Path.of(".")); + + assertEquals("demo", context.projectKey()); + assertEquals("pbs", context.languageId()); + assertEquals(Path.of(".").toAbsolutePath().normalize(), context.projectRoot()); + + assertThrows(IllegalArgumentException.class, () -> new LspProjectContext(" ", "pbs", Path.of("."))); + assertThrows(IllegalArgumentException.class, () -> new LspProjectContext("demo", " ", Path.of("."))); + } +} diff --git a/prometeu-lsp/prometeu-lsp-v1/build.gradle.kts b/prometeu-lsp/prometeu-lsp-v1/build.gradle.kts index 70154dda..082335f3 100644 --- a/prometeu-lsp/prometeu-lsp-v1/build.gradle.kts +++ b/prometeu-lsp/prometeu-lsp-v1/build.gradle.kts @@ -3,7 +3,7 @@ plugins { } dependencies { - implementation(project(":prometeu-infra")) - - implementation("org.eclipse.lsp4j:org.eclipse.lsp4j:1.0.0") -} \ No newline at end of file + implementation(project(":prometeu-lsp:prometeu-lsp-api")) + implementation(project(":prometeu-compiler:prometeu-build-pipeline")) + implementation(libs.lsp4j) +} diff --git a/prometeu-lsp/prometeu-lsp-v1/src/main/java/p/studio/lsp/PrometeuStudioLspMain.java b/prometeu-lsp/prometeu-lsp-v1/src/main/java/p/studio/lsp/PrometeuStudioLspMain.java deleted file mode 100644 index 5fc34565..00000000 --- a/prometeu-lsp/prometeu-lsp-v1/src/main/java/p/studio/lsp/PrometeuStudioLspMain.java +++ /dev/null @@ -1,271 +0,0 @@ -package p.studio.lsp; - -import org.eclipse.lsp4j.*; -import org.eclipse.lsp4j.jsonrpc.Launcher; -import org.eclipse.lsp4j.launch.LSPLauncher; -import org.eclipse.lsp4j.services.*; - -import java.io.InputStream; -import java.io.OutputStream; -import java.net.InetAddress; -import java.net.ServerSocket; -import java.net.Socket; -import java.util.List; -import java.util.concurrent.CompletableFuture; - -public final class PrometeuStudioLspMain { - - private static final String HOST = "127.0.0.1"; - private static final int PORT = 7777; - - public static void main(String[] args) throws Exception { - InetAddress bindAddress = InetAddress.getByName(HOST); - - try (ServerSocket serverSocket = new ServerSocket(PORT, 50, bindAddress)) { - System.out.println("Prometeu Studio LSP listening on " + HOST + ":" + PORT); - - while (true) { - Socket socket = serverSocket.accept(); - - Thread clientThread = new Thread(() -> handleClient(socket)); - clientThread.setName("prometeu-lsp-client"); - clientThread.setDaemon(true); - clientThread.start(); - } - } - } - - private static void handleClient(Socket socket) { - try { - System.out.println("VS Code connected: " + socket.getRemoteSocketAddress()); - - InputStream input = socket.getInputStream(); - OutputStream output = socket.getOutputStream(); - - PrometeuLanguageServer server = new PrometeuLanguageServer(); - - Launcher launcher = - LSPLauncher.createServerLauncher(server, input, output); - - LanguageClient client = launcher.getRemoteProxy(); - server.connect(client); - - launcher.startListening(); - - } catch (Exception e) { - System.err.println("LSP client failed: " + e.getMessage()); - e.printStackTrace(); - } - } - - private static final class PrometeuLanguageServer implements LanguageServer, LanguageClientAware { - - private LanguageClient client; - private final TextDocumentService textDocumentService = new PrometeuTextDocumentService(this); - private final WorkspaceService workspaceService = new PrometeuWorkspaceService(); - - private boolean shutdownRequested = false; - - @Override - public void connect(LanguageClient client) { - this.client = client; - - if (textDocumentService instanceof PrometeuTextDocumentService service) { - service.connect(client); - } - } - - public LanguageClient client() { - return client; - } - - @Override - public CompletableFuture initialize(InitializeParams params) { - ServerCapabilities capabilities = new ServerCapabilities(); - - TextDocumentSyncOptions syncOptions = new TextDocumentSyncOptions(); - syncOptions.setOpenClose(true); - syncOptions.setChange(TextDocumentSyncKind.Full); - - SaveOptions saveOptions = new SaveOptions(); - saveOptions.setIncludeText(true); - syncOptions.setSave(saveOptions); - - capabilities.setTextDocumentSync(syncOptions); - capabilities.setHoverProvider(true); - - InitializeResult result = new InitializeResult(capabilities); - - ServerInfo serverInfo = new ServerInfo(); - serverInfo.setName("Prometeu Studio LSP"); - serverInfo.setVersion("0.1.0"); - result.setServerInfo(serverInfo); - - return CompletableFuture.completedFuture(result); - } - - @Override - public void initialized(InitializedParams params) { - if (client != null) { - client.logMessage(new MessageParams( - MessageType.Info, - "Hello from Prometeu Studio LSP" - )); - } - } - - @Override - public CompletableFuture shutdown() { - shutdownRequested = true; - return CompletableFuture.completedFuture(null); - } - - @Override - public void exit() { - System.out.println("LSP client requested exit. shutdownRequested=" + shutdownRequested); - - // Importantíssimo: - // Como isso está dentro do Studio, NÃO use System.exit(). - } - - @Override - public TextDocumentService getTextDocumentService() { - return textDocumentService; - } - - @Override - public WorkspaceService getWorkspaceService() { - return workspaceService; - } - } - - private static final class PrometeuTextDocumentService implements TextDocumentService { - - private final PrometeuLanguageServer server; - private LanguageClient client; - - private PrometeuTextDocumentService(PrometeuLanguageServer server) { - this.server = server; - } - - private void connect(LanguageClient client) { - this.client = client; - } - - @Override - public void didOpen(DidOpenTextDocumentParams params) { - String uri = params.getTextDocument().getUri(); - String text = params.getTextDocument().getText(); - - System.out.println("didOpen: " + uri); - - publishHelloDiagnostic(uri, text); - } - - @Override - public void didChange(DidChangeTextDocumentParams params) { - String uri = params.getTextDocument().getUri(); - - String text = ""; - if (!params.getContentChanges().isEmpty()) { - text = params.getContentChanges().get(0).getText(); - } - - System.out.println("didChange: " + uri); - - publishHelloDiagnostic(uri, text); - } - - @Override - public void didClose(DidCloseTextDocumentParams params) { - String uri = params.getTextDocument().getUri(); - - System.out.println("didClose: " + uri); - - if (client != null) { - client.publishDiagnostics(new PublishDiagnosticsParams(uri, List.of())); - } - } - - @Override - public void didSave(DidSaveTextDocumentParams params) { - String uri = params.getTextDocument().getUri(); - - System.out.println("didSave: " + uri); - - if (client != null) { - client.logMessage(new MessageParams( - MessageType.Info, - "Prometeu Studio saw save: " + uri - )); - } - } - - @Override - public CompletableFuture hover(HoverParams params) { - MarkupContent content = new MarkupContent(); - content.setKind(MarkupKind.MARKDOWN); - content.setValue(""" - **Prometeu Studio LSP** - - Hello from Java + LSP4J. - - This hover came from the Studio process. - """); - - Hover hover = new Hover(); - hover.setContents(content); - - return CompletableFuture.completedFuture(hover); - } - - private void publishHelloDiagnostic(String uri, String text) { - if (client == null) { - return; - } - - Diagnostic diagnostic = new Diagnostic(); - - diagnostic.setRange(new Range( - new Position(0, 0), - new Position(0, Math.max(1, firstLineLength(text))) - )); - - diagnostic.setSeverity(DiagnosticSeverity.Information); - diagnostic.setSource("Prometeu Studio"); - diagnostic.setMessage("Hello from Prometeu Studio LSP"); - - client.publishDiagnostics(new PublishDiagnosticsParams( - uri, - List.of(diagnostic) - )); - } - - private int firstLineLength(String text) { - if (text == null || text.isEmpty()) { - return 1; - } - - int newline = text.indexOf('\n'); - - if (newline < 0) { - return text.length(); - } - - return newline; - } - } - - private static final class PrometeuWorkspaceService implements WorkspaceService { - - @Override - public void didChangeConfiguration(DidChangeConfigurationParams params) { - System.out.println("didChangeConfiguration"); - } - - @Override - public void didChangeWatchedFiles(DidChangeWatchedFilesParams params) { - System.out.println("didChangeWatchedFiles: " + params.getChanges().size() + " changes"); - } - } -} \ No newline at end of file diff --git a/prometeu-lsp/prometeu-lsp-v1/src/main/java/p/studio/lsp/v1/PrometeuStudioLspMain.java b/prometeu-lsp/prometeu-lsp-v1/src/main/java/p/studio/lsp/v1/PrometeuStudioLspMain.java new file mode 100644 index 00000000..8cb8a407 --- /dev/null +++ b/prometeu-lsp/prometeu-lsp-v1/src/main/java/p/studio/lsp/v1/PrometeuStudioLspMain.java @@ -0,0 +1,29 @@ +package p.studio.lsp.v1; + +import p.studio.lsp.api.LspProjectContext; +import p.studio.lsp.api.LspServerBootRequest; +import p.studio.lsp.v1.bootstrap.LspV1ServerLifecycle; +import p.studio.lsp.v1.compiler.CompilerLanguageServiceBridge; +import p.studio.lsp.v1.host.TcpLspServerHostFactory; + +import java.nio.file.Path; + +public final class PrometeuStudioLspMain { + private PrometeuStudioLspMain() { + } + + public static void main(final String[] args) throws Exception { + final var lifecycle = new LspV1ServerLifecycle( + new TcpLspServerHostFactory(), + new CompilerLanguageServiceBridge()); + + final var request = LspServerBootRequest.defaults(new LspProjectContext( + "standalone-mock", + "pbs", + Path.of("."))); + + final var handle = lifecycle.bootServer(request); + System.out.println("Prometeu Studio LSP listening on " + handle.endpoint().host() + ":" + handle.endpoint().port()); + Thread.currentThread().join(); + } +} diff --git a/prometeu-lsp/prometeu-lsp-v1/src/main/java/p/studio/lsp/v1/bootstrap/LspV1ServerLifecycle.java b/prometeu-lsp/prometeu-lsp-v1/src/main/java/p/studio/lsp/v1/bootstrap/LspV1ServerLifecycle.java new file mode 100644 index 00000000..40c6e258 --- /dev/null +++ b/prometeu-lsp/prometeu-lsp-v1/src/main/java/p/studio/lsp/v1/bootstrap/LspV1ServerLifecycle.java @@ -0,0 +1,64 @@ +package p.studio.lsp.v1.bootstrap; + +import p.studio.lsp.api.LspProjectContext; +import p.studio.lsp.api.LspServerBootRequest; +import p.studio.lsp.api.LspServerHandle; +import p.studio.lsp.api.LspServerLifecycle; +import p.studio.lsp.v1.compiler.CompilerLanguageServiceBridge; +import p.studio.lsp.v1.host.ProjectScopedLspServerHost; +import p.studio.lsp.v1.host.ProjectScopedLspServerHostFactory; + +import java.util.Objects; +import java.util.concurrent.ConcurrentHashMap; +import java.util.concurrent.ConcurrentMap; + +public final class LspV1ServerLifecycle implements LspServerLifecycle { + private final ProjectScopedLspServerHostFactory serverHostFactory; + private final CompilerLanguageServiceBridge compilerBridge; + private final ConcurrentMap activeServers; + + public LspV1ServerLifecycle( + final ProjectScopedLspServerHostFactory serverHostFactory, + final CompilerLanguageServiceBridge compilerBridge) { + this.serverHostFactory = Objects.requireNonNull(serverHostFactory, "serverHostFactory"); + this.compilerBridge = Objects.requireNonNull(compilerBridge, "compilerBridge"); + this.activeServers = new ConcurrentHashMap<>(); + } + + @Override + public LspServerHandle bootServer(final LspServerBootRequest request) { + final LspServerBootRequest safeRequest = Objects.requireNonNull(request, "request"); + final ProjectScopedLspServerHost host = serverHostFactory.create(safeRequest, compilerBridge); + final ProjectScopedLspServerHost previous = activeServers.putIfAbsent(safeRequest.project().projectKey(), host); + if (previous != null) { + throw new IllegalStateException("LSP server already booted for project " + safeRequest.project().projectKey()); + } + + try { + final var endpoint = host.start(); + return new LspServerHandle(safeRequest.project(), endpoint); + } catch (RuntimeException runtimeException) { + activeServers.remove(safeRequest.project().projectKey(), host); + closeQuietly(host); + throw runtimeException; + } + } + + @Override + public void shutdownServer(final LspProjectContext project) { + final LspProjectContext safeProject = Objects.requireNonNull(project, "project"); + final ProjectScopedLspServerHost host = activeServers.remove(safeProject.projectKey()); + if (host == null) { + return; + } + closeQuietly(host); + } + + private static void closeQuietly(final ProjectScopedLspServerHost host) { + try { + host.close(); + } catch (Exception exception) { + throw new IllegalStateException("failed to close LSP host", exception); + } + } +} diff --git a/prometeu-lsp/prometeu-lsp-v1/src/main/java/p/studio/lsp/v1/compiler/CompilerLanguageServiceBridge.java b/prometeu-lsp/prometeu-lsp-v1/src/main/java/p/studio/lsp/v1/compiler/CompilerLanguageServiceBridge.java new file mode 100644 index 00000000..6495745b --- /dev/null +++ b/prometeu-lsp/prometeu-lsp-v1/src/main/java/p/studio/lsp/v1/compiler/CompilerLanguageServiceBridge.java @@ -0,0 +1,21 @@ +package p.studio.lsp.v1.compiler; + +import p.studio.compiler.workspaces.BuilderPipelineService; + +import java.util.Objects; + +public final class CompilerLanguageServiceBridge { + private final BuilderPipelineService builderPipelineService; + + public CompilerLanguageServiceBridge() { + this(BuilderPipelineService.INSTANCE); + } + + public CompilerLanguageServiceBridge(final BuilderPipelineService builderPipelineService) { + this.builderPipelineService = Objects.requireNonNull(builderPipelineService, "builderPipelineService"); + } + + public BuilderPipelineService builderPipelineService() { + return builderPipelineService; + } +} diff --git a/prometeu-lsp/prometeu-lsp-v1/src/main/java/p/studio/lsp/v1/host/ProjectScopedLspServerHost.java b/prometeu-lsp/prometeu-lsp-v1/src/main/java/p/studio/lsp/v1/host/ProjectScopedLspServerHost.java new file mode 100644 index 00000000..b3a847a5 --- /dev/null +++ b/prometeu-lsp/prometeu-lsp-v1/src/main/java/p/studio/lsp/v1/host/ProjectScopedLspServerHost.java @@ -0,0 +1,10 @@ +package p.studio.lsp.v1.host; + +import p.studio.lsp.api.LspServerEndpoint; + +public interface ProjectScopedLspServerHost extends AutoCloseable { + LspServerEndpoint start(); + + @Override + void close() throws Exception; +} diff --git a/prometeu-lsp/prometeu-lsp-v1/src/main/java/p/studio/lsp/v1/host/ProjectScopedLspServerHostFactory.java b/prometeu-lsp/prometeu-lsp-v1/src/main/java/p/studio/lsp/v1/host/ProjectScopedLspServerHostFactory.java new file mode 100644 index 00000000..8b46b58a --- /dev/null +++ b/prometeu-lsp/prometeu-lsp-v1/src/main/java/p/studio/lsp/v1/host/ProjectScopedLspServerHostFactory.java @@ -0,0 +1,10 @@ +package p.studio.lsp.v1.host; + +import p.studio.lsp.api.LspServerBootRequest; +import p.studio.lsp.v1.compiler.CompilerLanguageServiceBridge; + +public interface ProjectScopedLspServerHostFactory { + ProjectScopedLspServerHost create( + LspServerBootRequest request, + CompilerLanguageServiceBridge compilerBridge); +} diff --git a/prometeu-lsp/prometeu-lsp-v1/src/main/java/p/studio/lsp/v1/host/TcpLspServerHost.java b/prometeu-lsp/prometeu-lsp-v1/src/main/java/p/studio/lsp/v1/host/TcpLspServerHost.java new file mode 100644 index 00000000..5d14c2c6 --- /dev/null +++ b/prometeu-lsp/prometeu-lsp-v1/src/main/java/p/studio/lsp/v1/host/TcpLspServerHost.java @@ -0,0 +1,101 @@ +package p.studio.lsp.v1.host; + +import org.eclipse.lsp4j.jsonrpc.Launcher; +import org.eclipse.lsp4j.launch.LSPLauncher; +import org.eclipse.lsp4j.services.LanguageClient; +import p.studio.lsp.api.LspServerBootRequest; +import p.studio.lsp.api.LspServerEndpoint; +import p.studio.lsp.v1.compiler.CompilerLanguageServiceBridge; +import p.studio.lsp.v1.protocol.PrometeuLanguageServer; + +import java.io.IOException; +import java.net.InetAddress; +import java.net.ServerSocket; +import java.net.Socket; +import java.util.Objects; +import java.util.concurrent.ExecutorService; +import java.util.concurrent.Executors; + +public final class TcpLspServerHost implements ProjectScopedLspServerHost { + private final LspServerBootRequest request; + private final CompilerLanguageServiceBridge compilerBridge; + private final ExecutorService clientExecutor; + private volatile boolean closed; + private volatile ServerSocket serverSocket; + private volatile Thread acceptThread; + private volatile LspServerEndpoint endpoint; + + public TcpLspServerHost( + final LspServerBootRequest request, + final CompilerLanguageServiceBridge compilerBridge) { + this.request = Objects.requireNonNull(request, "request"); + this.compilerBridge = Objects.requireNonNull(compilerBridge, "compilerBridge"); + this.clientExecutor = Executors.newCachedThreadPool(runnable -> { + final Thread thread = new Thread(runnable); + thread.setName("prometeu-lsp-v1-client"); + thread.setDaemon(true); + return thread; + }); + } + + @Override + public synchronized LspServerEndpoint start() { + if (endpoint != null) { + return endpoint; + } + try { + final InetAddress bindAddress = InetAddress.getByName(request.configuration().host()); + final ServerSocket socket = new ServerSocket(request.configuration().port(), 50, bindAddress); + serverSocket = socket; + endpoint = new LspServerEndpoint(bindAddress.getHostAddress(), socket.getLocalPort()); + acceptThread = new Thread(this::acceptLoop, "prometeu-lsp-v1-accept"); + acceptThread.setDaemon(true); + acceptThread.start(); + return endpoint; + } catch (IOException exception) { + throw new IllegalStateException("failed to start TCP LSP host", exception); + } + } + + private void acceptLoop() { + while (!closed) { + try { + final Socket socket = serverSocket.accept(); + clientExecutor.submit(() -> handleClient(socket)); + } catch (IOException exception) { + if (!closed) { + throw new IllegalStateException("failed to accept LSP client", exception); + } + } + } + } + + private void handleClient(final Socket socket) { + try (socket) { + final var server = new PrometeuLanguageServer(request.project(), compilerBridge); + final Launcher launcher = LSPLauncher.createServerLauncher( + server, + socket.getInputStream(), + socket.getOutputStream()); + server.connect(launcher.getRemoteProxy()); + launcher.startListening().get(); + } catch (Exception exception) { + throw new IllegalStateException("LSP client failed", exception); + } + } + + @Override + public synchronized void close() throws Exception { + if (closed) { + return; + } + closed = true; + if (serverSocket != null) { + serverSocket.close(); + } + if (acceptThread != null) { + acceptThread.interrupt(); + } + clientExecutor.shutdownNow(); + } +} diff --git a/prometeu-lsp/prometeu-lsp-v1/src/main/java/p/studio/lsp/v1/host/TcpLspServerHostFactory.java b/prometeu-lsp/prometeu-lsp-v1/src/main/java/p/studio/lsp/v1/host/TcpLspServerHostFactory.java new file mode 100644 index 00000000..d8713f5a --- /dev/null +++ b/prometeu-lsp/prometeu-lsp-v1/src/main/java/p/studio/lsp/v1/host/TcpLspServerHostFactory.java @@ -0,0 +1,13 @@ +package p.studio.lsp.v1.host; + +import p.studio.lsp.api.LspServerBootRequest; +import p.studio.lsp.v1.compiler.CompilerLanguageServiceBridge; + +public final class TcpLspServerHostFactory implements ProjectScopedLspServerHostFactory { + @Override + public ProjectScopedLspServerHost create( + final LspServerBootRequest request, + final CompilerLanguageServiceBridge compilerBridge) { + return new TcpLspServerHost(request, compilerBridge); + } +} diff --git a/prometeu-lsp/prometeu-lsp-v1/src/main/java/p/studio/lsp/v1/protocol/PrometeuLanguageServer.java b/prometeu-lsp/prometeu-lsp-v1/src/main/java/p/studio/lsp/v1/protocol/PrometeuLanguageServer.java new file mode 100644 index 00000000..d10f225b --- /dev/null +++ b/prometeu-lsp/prometeu-lsp-v1/src/main/java/p/studio/lsp/v1/protocol/PrometeuLanguageServer.java @@ -0,0 +1,101 @@ +package p.studio.lsp.v1.protocol; + +import org.eclipse.lsp4j.*; +import org.eclipse.lsp4j.services.LanguageClient; +import org.eclipse.lsp4j.services.LanguageClientAware; +import org.eclipse.lsp4j.services.LanguageServer; +import org.eclipse.lsp4j.services.TextDocumentService; +import org.eclipse.lsp4j.services.WorkspaceService; +import p.studio.lsp.api.LspProjectContext; +import p.studio.lsp.v1.compiler.CompilerLanguageServiceBridge; +import p.studio.lsp.v1.protocol.mapping.ProtocolServerProfile; +import p.studio.lsp.v1.protocol.mapping.ServerCapabilitiesMapper; + +import java.util.Objects; +import java.util.concurrent.CompletableFuture; + +public final class PrometeuLanguageServer implements LanguageServer, LanguageClientAware { + private final LspProjectContext project; + private final CompilerLanguageServiceBridge compilerBridge; + private final ServerCapabilitiesMapper capabilitiesMapper; + private final TextDocumentService textDocumentService; + private final WorkspaceService workspaceService; + private volatile LanguageClient client; + private volatile boolean shutdownRequested; + + public PrometeuLanguageServer( + final LspProjectContext project, + final CompilerLanguageServiceBridge compilerBridge) { + this(project, + compilerBridge, + new ServerCapabilitiesMapper(), + new PrometeuTextDocumentService(), + new PrometeuWorkspaceService()); + } + + PrometeuLanguageServer( + final LspProjectContext project, + final CompilerLanguageServiceBridge compilerBridge, + final ServerCapabilitiesMapper capabilitiesMapper, + final TextDocumentService textDocumentService, + final WorkspaceService workspaceService) { + this.project = Objects.requireNonNull(project, "project"); + this.compilerBridge = Objects.requireNonNull(compilerBridge, "compilerBridge"); + this.capabilitiesMapper = Objects.requireNonNull(capabilitiesMapper, "capabilitiesMapper"); + this.textDocumentService = Objects.requireNonNull(textDocumentService, "textDocumentService"); + this.workspaceService = Objects.requireNonNull(workspaceService, "workspaceService"); + } + + @Override + public void connect(final LanguageClient client) { + this.client = client; + if (textDocumentService instanceof PrometeuTextDocumentService service) { + service.connect(client); + } + } + + @Override + public CompletableFuture initialize(final InitializeParams params) { + final ProtocolServerProfile profile = ProtocolServerProfile.defaults(); + return CompletableFuture.completedFuture(capabilitiesMapper.map(profile)); + } + + @Override + public void initialized(final InitializedParams params) { + final LanguageClient currentClient = client; + if (currentClient == null) { + return; + } + currentClient.logMessage(new MessageParams( + MessageType.Info, + "Prometeu Studio LSP connected for project " + project.projectKey())); + } + + @Override + public CompletableFuture shutdown() { + shutdownRequested = true; + return CompletableFuture.completedFuture(null); + } + + @Override + public void exit() { + if (!shutdownRequested) { + final LanguageClient currentClient = client; + if (currentClient != null) { + currentClient.logMessage(new MessageParams( + MessageType.Warning, + "Prometeu Studio LSP received exit before shutdown")); + } + } + } + + @Override + public TextDocumentService getTextDocumentService() { + return textDocumentService; + } + + @Override + public WorkspaceService getWorkspaceService() { + return workspaceService; + } +} diff --git a/prometeu-lsp/prometeu-lsp-v1/src/main/java/p/studio/lsp/v1/protocol/PrometeuTextDocumentService.java b/prometeu-lsp/prometeu-lsp-v1/src/main/java/p/studio/lsp/v1/protocol/PrometeuTextDocumentService.java new file mode 100644 index 00000000..952e2772 --- /dev/null +++ b/prometeu-lsp/prometeu-lsp-v1/src/main/java/p/studio/lsp/v1/protocol/PrometeuTextDocumentService.java @@ -0,0 +1,93 @@ +package p.studio.lsp.v1.protocol; + +import org.eclipse.lsp4j.*; +import org.eclipse.lsp4j.services.LanguageClient; +import org.eclipse.lsp4j.services.TextDocumentService; + +import java.util.List; +import java.util.concurrent.CompletableFuture; + +public final class PrometeuTextDocumentService implements TextDocumentService { + private volatile LanguageClient client; + + void connect(final LanguageClient client) { + this.client = client; + } + + @Override + public void didOpen(final DidOpenTextDocumentParams params) { + publishHelloDiagnostic(params.getTextDocument().getUri(), params.getTextDocument().getText()); + } + + @Override + public void didChange(final DidChangeTextDocumentParams params) { + final String text = params.getContentChanges().isEmpty() + ? "" + : params.getContentChanges().getFirst().getText(); + publishHelloDiagnostic(params.getTextDocument().getUri(), text); + } + + @Override + public void didClose(final DidCloseTextDocumentParams params) { + final LanguageClient currentClient = client; + if (currentClient == null) { + return; + } + currentClient.publishDiagnostics(new PublishDiagnosticsParams(params.getTextDocument().getUri(), List.of())); + } + + @Override + public void didSave(final DidSaveTextDocumentParams params) { + final LanguageClient currentClient = client; + if (currentClient == null) { + return; + } + currentClient.logMessage(new MessageParams( + MessageType.Info, + "Prometeu Studio saw save: " + params.getTextDocument().getUri())); + } + + @Override + public CompletableFuture hover(final HoverParams params) { + final MarkupContent content = new MarkupContent(); + content.setKind(MarkupKind.MARKDOWN); + content.setValue(""" + **Prometeu Studio LSP** + + Structured baseline server. + + Semantic enrichment will be layered later. + """); + + final Hover hover = new Hover(); + hover.setContents(content); + return CompletableFuture.completedFuture(hover); + } + + private void publishHelloDiagnostic( + final String uri, + final String text) { + final LanguageClient currentClient = client; + if (currentClient == null) { + return; + } + + final Diagnostic diagnostic = new Diagnostic(); + diagnostic.setRange(new Range( + new Position(0, 0), + new Position(0, Math.max(1, firstLineLength(text))))); + diagnostic.setSeverity(DiagnosticSeverity.Information); + diagnostic.setSource("Prometeu Studio"); + diagnostic.setMessage("Structured baseline LSP response"); + + currentClient.publishDiagnostics(new PublishDiagnosticsParams(uri, List.of(diagnostic))); + } + + private int firstLineLength(final String text) { + if (text == null || text.isEmpty()) { + return 1; + } + final int newline = text.indexOf('\n'); + return newline < 0 ? text.length() : newline; + } +} diff --git a/prometeu-lsp/prometeu-lsp-v1/src/main/java/p/studio/lsp/v1/protocol/PrometeuWorkspaceService.java b/prometeu-lsp/prometeu-lsp-v1/src/main/java/p/studio/lsp/v1/protocol/PrometeuWorkspaceService.java new file mode 100644 index 00000000..1a5efa8e --- /dev/null +++ b/prometeu-lsp/prometeu-lsp-v1/src/main/java/p/studio/lsp/v1/protocol/PrometeuWorkspaceService.java @@ -0,0 +1,15 @@ +package p.studio.lsp.v1.protocol; + +import org.eclipse.lsp4j.DidChangeConfigurationParams; +import org.eclipse.lsp4j.DidChangeWatchedFilesParams; +import org.eclipse.lsp4j.services.WorkspaceService; + +public final class PrometeuWorkspaceService implements WorkspaceService { + @Override + public void didChangeConfiguration(final DidChangeConfigurationParams params) { + } + + @Override + public void didChangeWatchedFiles(final DidChangeWatchedFilesParams params) { + } +} diff --git a/prometeu-lsp/prometeu-lsp-v1/src/main/java/p/studio/lsp/v1/protocol/mapping/ProtocolServerProfile.java b/prometeu-lsp/prometeu-lsp-v1/src/main/java/p/studio/lsp/v1/protocol/mapping/ProtocolServerProfile.java new file mode 100644 index 00000000..75b4bc8a --- /dev/null +++ b/prometeu-lsp/prometeu-lsp-v1/src/main/java/p/studio/lsp/v1/protocol/mapping/ProtocolServerProfile.java @@ -0,0 +1,11 @@ +package p.studio.lsp.v1.protocol.mapping; + +public record ProtocolServerProfile( + String name, + String version, + boolean hoverSupported) { + + public static ProtocolServerProfile defaults() { + return new ProtocolServerProfile("Prometeu Studio LSP", "0.1.0", true); + } +} diff --git a/prometeu-lsp/prometeu-lsp-v1/src/main/java/p/studio/lsp/v1/protocol/mapping/ServerCapabilitiesMapper.java b/prometeu-lsp/prometeu-lsp-v1/src/main/java/p/studio/lsp/v1/protocol/mapping/ServerCapabilitiesMapper.java new file mode 100644 index 00000000..5f5c4a0c --- /dev/null +++ b/prometeu-lsp/prometeu-lsp-v1/src/main/java/p/studio/lsp/v1/protocol/mapping/ServerCapabilitiesMapper.java @@ -0,0 +1,27 @@ +package p.studio.lsp.v1.protocol.mapping; + +import org.eclipse.lsp4j.*; + +public final class ServerCapabilitiesMapper { + public InitializeResult map(final ProtocolServerProfile profile) { + final ServerCapabilities capabilities = new ServerCapabilities(); + + final TextDocumentSyncOptions syncOptions = new TextDocumentSyncOptions(); + syncOptions.setOpenClose(true); + syncOptions.setChange(TextDocumentSyncKind.Full); + + final SaveOptions saveOptions = new SaveOptions(); + saveOptions.setIncludeText(true); + syncOptions.setSave(saveOptions); + + capabilities.setTextDocumentSync(syncOptions); + capabilities.setHoverProvider(profile.hoverSupported()); + + final InitializeResult result = new InitializeResult(capabilities); + final ServerInfo serverInfo = new ServerInfo(); + serverInfo.setName(profile.name()); + serverInfo.setVersion(profile.version()); + result.setServerInfo(serverInfo); + return result; + } +} diff --git a/prometeu-lsp/prometeu-lsp-v1/src/test/java/p/studio/lsp/v1/bootstrap/LspV1ServerLifecycleTest.java b/prometeu-lsp/prometeu-lsp-v1/src/test/java/p/studio/lsp/v1/bootstrap/LspV1ServerLifecycleTest.java new file mode 100644 index 00000000..38aa03b1 --- /dev/null +++ b/prometeu-lsp/prometeu-lsp-v1/src/test/java/p/studio/lsp/v1/bootstrap/LspV1ServerLifecycleTest.java @@ -0,0 +1,63 @@ +package p.studio.lsp.v1.bootstrap; + +import org.junit.jupiter.api.Test; +import p.studio.lsp.api.LspProjectContext; +import p.studio.lsp.api.LspServerBootRequest; +import p.studio.lsp.api.LspServerEndpoint; +import p.studio.lsp.v1.compiler.CompilerLanguageServiceBridge; +import p.studio.lsp.v1.host.ProjectScopedLspServerHost; +import p.studio.lsp.v1.host.ProjectScopedLspServerHostFactory; + +import java.nio.file.Path; + +import static org.junit.jupiter.api.Assertions.assertEquals; +import static org.junit.jupiter.api.Assertions.assertThrows; +import static org.junit.jupiter.api.Assertions.assertTrue; + +class LspV1ServerLifecycleTest { + + @Test + void lifecycleBootsAndShutsDownProjectScopedHost() { + final FakeHost host = new FakeHost(); + final ProjectScopedLspServerHostFactory factory = (request, compilerBridge) -> host; + final var lifecycle = new LspV1ServerLifecycle(factory, new CompilerLanguageServiceBridge()); + final var project = new LspProjectContext("demo", "pbs", Path.of(".")); + + final var handle = lifecycle.bootServer(LspServerBootRequest.defaults(project)); + + assertEquals(project, handle.project()); + assertEquals("127.0.0.1", handle.endpoint().host()); + assertEquals(7777, handle.endpoint().port()); + assertTrue(host.started); + + lifecycle.shutdownServer(project); + assertTrue(host.closed); + } + + @Test + void lifecycleRejectsDoubleBootForSameProject() { + final ProjectScopedLspServerHostFactory factory = (request, compilerBridge) -> new FakeHost(); + final var lifecycle = new LspV1ServerLifecycle(factory, new CompilerLanguageServiceBridge()); + final var request = LspServerBootRequest.defaults(new LspProjectContext("demo", "pbs", Path.of("."))); + + lifecycle.bootServer(request); + + assertThrows(IllegalStateException.class, () -> lifecycle.bootServer(request)); + } + + private static final class FakeHost implements ProjectScopedLspServerHost { + private boolean started; + private boolean closed; + + @Override + public LspServerEndpoint start() { + started = true; + return new LspServerEndpoint("127.0.0.1", 7777); + } + + @Override + public void close() { + closed = true; + } + } +} diff --git a/prometeu-lsp/prometeu-lsp-v1/src/test/java/p/studio/lsp/v1/boundary/LspV1BoundaryTest.java b/prometeu-lsp/prometeu-lsp-v1/src/test/java/p/studio/lsp/v1/boundary/LspV1BoundaryTest.java new file mode 100644 index 00000000..dc380fd7 --- /dev/null +++ b/prometeu-lsp/prometeu-lsp-v1/src/test/java/p/studio/lsp/v1/boundary/LspV1BoundaryTest.java @@ -0,0 +1,46 @@ +package p.studio.lsp.v1.boundary; + +import org.junit.jupiter.api.Test; + +import java.io.IOException; +import java.nio.file.Files; +import java.nio.file.Path; +import java.util.List; + +import static org.junit.jupiter.api.Assertions.assertTrue; + +class LspV1BoundaryTest { + + @Test + void lsp4jMustRemainContainedInsideLspV1Sources() throws IOException { + final List forbiddenRoots = List.of( + Path.of("../prometeu-lsp-api/src/main/java"), + Path.of("../../../prometeu-studio/src/main/java"), + Path.of("../../../prometeu-app/src/main/java"), + Path.of("../../../prometeu-compiler"), + Path.of("../../../prometeu-packer"), + Path.of("../../../prometeu-infra")); + + for (final Path root : forbiddenRoots) { + assertNoLsp4jImports(root.normalize()); + } + } + + private static void assertNoLsp4jImports(final Path root) throws IOException { + if (!Files.exists(root)) { + return; + } + final List javaFiles; + try (var stream = Files.walk(root)) { + javaFiles = stream + .filter(path -> path.toString().endsWith(".java")) + .toList(); + } + + for (final Path javaFile : javaFiles) { + final String source = Files.readString(javaFile); + assertTrue(!source.contains("org.eclipse.lsp4j"), + () -> "LSP4J leaked outside lsp-v1: " + javaFile); + } + } +} -- 2.47.2 From 18dc64e36c6302ef1dac43cef1be2c7daafa8abf Mon Sep 17 00:00:00 2001 From: bQUARKz Date: Tue, 5 May 2026 15:54:11 +0100 Subject: [PATCH 07/37] implements PLN-0066 --- discussion/index.ndjson | 2 +- ...t-scoped-lsp-server-lifecycle-in-studio.md | 14 ++-- prometeu-app/build.gradle.kts | 2 + .../src/main/java/p/studio/AppContainer.java | 13 ++++ prometeu-studio/build.gradle.kts | 1 + .../src/main/java/p/studio/Container.java | 7 ++ .../projectsessions/StudioProjectSession.java | 31 ++++++++- .../StudioProjectSessionFactory.java | 31 +++++++-- .../window/StudioWindowCoordinator.java | 2 +- .../StudioProjectSessionFactoryTest.java | 64 ++++++++++++++++++- .../StudioProjectSessionTest.java | 46 +++++++++++++ 11 files changed, 195 insertions(+), 18 deletions(-) diff --git a/discussion/index.ndjson b/discussion/index.ndjson index a54cea18..105c34f9 100644 --- a/discussion/index.ndjson +++ b/discussion/index.ndjson @@ -1,5 +1,5 @@ {"type":"meta","next_id":{"DSC":33,"AGD":36,"DEC":33,"PLN":68,"LSN":47,"CLSN":1}} -{"type":"discussion","id":"DSC-0032","status":"in_progress","ticket":"studio-new-lsp-api-and-v1-boundary","title":"Novo boundary entre lsp-api, lsp-v1 e a extensao VS Code","created_at":"2026-05-05","updated_at":"2026-05-05","tags":["studio","lsp","vscode","protocol","api","boundary"],"agendas":[{"id":"AGD-0035","file":"AGD-0035-studio-new-lsp-api-and-v1-boundary.md","status":"accepted","created_at":"2026-05-05","updated_at":"2026-05-05"}],"decisions":[{"id":"DEC-0032","file":"DEC-0032-studio-new-lsp-api-and-v1-boundary.md","status":"accepted","created_at":"2026-05-05","updated_at":"2026-05-05","ref_agenda":"AGD-0035"}],"plans":[{"id":"PLN-0065","file":"PLN-0065-lsp-boundary-and-module-scaffolding.md","status":"done","created_at":"2026-05-05","updated_at":"2026-05-05","ref_decisions":["DEC-0032"]},{"id":"PLN-0066","file":"PLN-0066-project-scoped-lsp-server-lifecycle-in-studio.md","status":"open","created_at":"2026-05-05","updated_at":"2026-05-05","ref_decisions":["DEC-0032"]},{"id":"PLN-0067","file":"PLN-0067-compiler-backed-dumb-lsp-server-baseline.md","status":"open","created_at":"2026-05-05","updated_at":"2026-05-05","ref_decisions":["DEC-0032"]}],"lessons":[]} +{"type":"discussion","id":"DSC-0032","status":"in_progress","ticket":"studio-new-lsp-api-and-v1-boundary","title":"Novo boundary entre lsp-api, lsp-v1 e a extensao VS Code","created_at":"2026-05-05","updated_at":"2026-05-05","tags":["studio","lsp","vscode","protocol","api","boundary"],"agendas":[{"id":"AGD-0035","file":"AGD-0035-studio-new-lsp-api-and-v1-boundary.md","status":"accepted","created_at":"2026-05-05","updated_at":"2026-05-05"}],"decisions":[{"id":"DEC-0032","file":"DEC-0032-studio-new-lsp-api-and-v1-boundary.md","status":"accepted","created_at":"2026-05-05","updated_at":"2026-05-05","ref_agenda":"AGD-0035"}],"plans":[{"id":"PLN-0065","file":"PLN-0065-lsp-boundary-and-module-scaffolding.md","status":"done","created_at":"2026-05-05","updated_at":"2026-05-05","ref_decisions":["DEC-0032"]},{"id":"PLN-0066","file":"PLN-0066-project-scoped-lsp-server-lifecycle-in-studio.md","status":"done","created_at":"2026-05-05","updated_at":"2026-05-05","ref_decisions":["DEC-0032"]},{"id":"PLN-0067","file":"PLN-0067-compiler-backed-dumb-lsp-server-baseline.md","status":"open","created_at":"2026-05-05","updated_at":"2026-05-05","ref_decisions":["DEC-0032"]}],"lessons":[]} {"type":"discussion","id":"DSC-0031","status":"in_progress","ticket":"studio-editor-workspace-cleanup","title":"Limpeza completa do Workspace Editor do Studio e remoção dos acoplamentos legados","created_at":"2026-05-05","updated_at":"2026-05-05","tags":["studio","editor","cleanup","vfs","lsp","migration"],"agendas":[{"id":"AGD-0034","file":"AGD-0034-vscode-editor-migration-feasibility.md","status":"accepted","created_at":"2026-05-05","updated_at":"2026-05-05"}],"decisions":[{"id":"DEC-0031","file":"DEC-0031-studio-editor-workspace-cleanup.md","status":"in_progress","created_at":"2026-05-05","updated_at":"2026-05-05","ref_agenda":"AGD-0034"}],"plans":[{"id":"PLN-0062","file":"PLN-0062-shell-session-and-state-cleanup-after-editor-removal.md","status":"done","created_at":"2026-05-05","updated_at":"2026-05-05","ref_decisions":["DEC-0031"]},{"id":"PLN-0063","file":"PLN-0063-legacy-lsp-and-vfs-module-removal-with-runtime-preservation.md","status":"done","created_at":"2026-05-05","updated_at":"2026-05-05","ref_decisions":["DEC-0031"]},{"id":"PLN-0064","file":"PLN-0064-normative-test-and-lesson-cleanup-for-editor-stack-removal.md","status":"done","created_at":"2026-05-05","updated_at":"2026-05-05","ref_decisions":["DEC-0031"]}],"lessons":[]} {"type":"discussion","id":"DSC-0030","status":"done","ticket":"studio-scene-pack-runtime-binary-contract","title":"Studio scene pack contract for runtime SCENE binary payload","created_at":"2026-04-24","updated_at":"2026-05-01","tags":["studio","packer","runtime","scene","asset-pack","binary-format","tiled"],"agendas":[],"decisions":[],"plans":[],"lessons":[{"id":"LSN-0046","file":"discussion/lessons/DSC-0030-studio-scene-pack-runtime-binary-contract/LSN-0046-canonical-scene-owns-editorial-truth-while-pack-stays-request-driven.md","status":"done","created_at":"2026-05-01","updated_at":"2026-05-01"}]} {"type":"discussion","id":"DSC-0029","status":"done","ticket":"studio-frame-composer-syscall-and-sprite-alignment","title":"Studio Alignment with Runtime FrameComposer Syscalls and Sprite Composition","created_at":"2026-04-18","updated_at":"2026-04-18","tags":["studio","compiler","pbs","stdlib","runtime-alignment","abi","syscall","frame-composer","sprites"],"agendas":[],"decisions":[],"plans":[],"lessons":[{"id":"LSN-0041","file":"discussion/lessons/DSC-0029-studio-frame-composer-syscall-and-sprite-alignment/LSN-0041-composer-must-own-public-sprite-composition.md","status":"done","created_at":"2026-04-18","updated_at":"2026-04-18"}]} diff --git a/discussion/workflow/plans/PLN-0066-project-scoped-lsp-server-lifecycle-in-studio.md b/discussion/workflow/plans/PLN-0066-project-scoped-lsp-server-lifecycle-in-studio.md index c6144269..14fa4f60 100644 --- a/discussion/workflow/plans/PLN-0066-project-scoped-lsp-server-lifecycle-in-studio.md +++ b/discussion/workflow/plans/PLN-0066-project-scoped-lsp-server-lifecycle-in-studio.md @@ -2,9 +2,9 @@ id: PLN-0066 ticket: studio-new-lsp-api-and-v1-boundary title: Project-Scoped LSP Server Lifecycle in Studio -status: open +status: done created: 2026-05-05 -completed: +completed: 2026-05-05 tags: [studio, lsp, lifecycle, projects, boot, shutdown] --- @@ -85,11 +85,11 @@ These surfaces already own project startup and teardown flow and therefore are t ## Acceptance Criteria -- [ ] Opening a Studio project boots an LSP server for that project. -- [ ] Closing the project shuts down that server. -- [ ] The lifecycle is owned by project session boundaries, not global app startup. -- [ ] Existing non-LSP project flows remain operational. -- [ ] The current dumb connectivity workflow remains usable as a temporary implementation phase. +- [x] Opening a Studio project boots an LSP server for that project. +- [x] Closing the project shuts down that server. +- [x] The lifecycle is owned by project session boundaries, not global app startup. +- [x] Existing non-LSP project flows remain operational. +- [x] The current dumb connectivity workflow remains usable as a temporary implementation phase. ## Dependencies diff --git a/prometeu-app/build.gradle.kts b/prometeu-app/build.gradle.kts index 59d3d29b..92e953ee 100644 --- a/prometeu-app/build.gradle.kts +++ b/prometeu-app/build.gradle.kts @@ -5,6 +5,8 @@ plugins { dependencies { implementation(project(":prometeu-infra")) + implementation(project(":prometeu-lsp:prometeu-lsp-api")) + implementation(project(":prometeu-lsp:prometeu-lsp-v1")) implementation(project(":prometeu-packer:prometeu-packer-api")) implementation(project(":prometeu-packer:prometeu-packer-v1")) implementation(project(":prometeu-studio")) diff --git a/prometeu-app/src/main/java/p/studio/AppContainer.java b/prometeu-app/src/main/java/p/studio/AppContainer.java index ec86a4b9..8bcaeb8f 100644 --- a/prometeu-app/src/main/java/p/studio/AppContainer.java +++ b/prometeu-app/src/main/java/p/studio/AppContainer.java @@ -2,8 +2,12 @@ package p.studio; import com.fasterxml.jackson.databind.ObjectMapper; import p.packer.Packer; +import p.studio.lsp.api.LspServerLifecycle; import p.studio.lsp.events.StudioEventBus; import p.studio.lsp.events.StudioPackerEventAdapter; +import p.studio.lsp.v1.bootstrap.LspV1ServerLifecycle; +import p.studio.lsp.v1.compiler.CompilerLanguageServiceBridge; +import p.studio.lsp.v1.host.TcpLspServerHostFactory; import p.studio.utilities.ThemeService; import p.studio.utilities.i18n.I18nService; @@ -19,6 +23,7 @@ public final class AppContainer implements Container { private final ObjectMapper mapper; private final EmbeddedPacker embeddedPacker; private final StudioBackgroundTasks backgroundTasks; + private final LspServerLifecycle lspServerLifecycle; public AppContainer() { this.i18nService = new I18nService(); @@ -29,6 +34,9 @@ public final class AppContainer implements Container { this.backgroundTasks = new StudioBackgroundTasks(backgroundExecutor); final Packer packer = Packer.bootstrap(this.mapper, new StudioPackerEventAdapter(studioEventBus)); this.embeddedPacker = new EmbeddedPacker(packer.workspaceService(), packer::close); + this.lspServerLifecycle = new LspV1ServerLifecycle( + new TcpLspServerHostFactory(), + new CompilerLanguageServiceBridge()); } @Override @@ -61,6 +69,11 @@ public final class AppContainer implements Container { return backgroundTasks; } + @Override + public LspServerLifecycle getLspServerLifecycle() { + return lspServerLifecycle; + } + @Override public void shutdownContainer() { embeddedPacker.shutdown(); diff --git a/prometeu-studio/build.gradle.kts b/prometeu-studio/build.gradle.kts index 57bf98cc..93d2ea90 100644 --- a/prometeu-studio/build.gradle.kts +++ b/prometeu-studio/build.gradle.kts @@ -5,6 +5,7 @@ plugins { dependencies { implementation(project(":prometeu-infra")) + implementation(project(":prometeu-lsp:prometeu-lsp-api")) implementation(project(":prometeu-packer:prometeu-packer-api")) implementation(project(":prometeu-compiler:prometeu-compiler-core")) implementation(project(":prometeu-compiler:prometeu-build-pipeline")) diff --git a/prometeu-studio/src/main/java/p/studio/Container.java b/prometeu-studio/src/main/java/p/studio/Container.java index 2e9cae4e..8af847e8 100644 --- a/prometeu-studio/src/main/java/p/studio/Container.java +++ b/prometeu-studio/src/main/java/p/studio/Container.java @@ -1,6 +1,7 @@ package p.studio; import com.fasterxml.jackson.databind.ObjectMapper; +import p.studio.lsp.api.LspServerLifecycle; import p.studio.lsp.events.StudioEventBus; import p.studio.utilities.ThemeService; import p.studio.utilities.i18n.I18nService; @@ -21,6 +22,8 @@ public interface Container { StudioBackgroundTasks getBackgroundTasks(); + LspServerLifecycle getLspServerLifecycle(); + void shutdownContainer(); static void install(Container container) { @@ -68,6 +71,10 @@ public interface Container { return current().getBackgroundTasks(); } + static LspServerLifecycle lspServerLifecycle() { + return current().getLspServerLifecycle(); + } + static void shutdown() { final Container container = Holder.CURRENT.get(); if (container != null) { diff --git a/prometeu-studio/src/main/java/p/studio/projectsessions/StudioProjectSession.java b/prometeu-studio/src/main/java/p/studio/projectsessions/StudioProjectSession.java index af36c5c7..3e2b08b5 100644 --- a/prometeu-studio/src/main/java/p/studio/projectsessions/StudioProjectSession.java +++ b/prometeu-studio/src/main/java/p/studio/projectsessions/StudioProjectSession.java @@ -1,6 +1,9 @@ package p.studio.projectsessions; import p.studio.execution.StudioExecutionSessionService; +import p.studio.lsp.api.LspProjectContext; +import p.studio.lsp.api.LspServerHandle; +import p.studio.lsp.api.LspServerLifecycle; import p.studio.projectstate.ProjectLocalStudioSetup; import p.studio.projectstate.ProjectLocalStudioState; import p.studio.projectstate.ProjectLocalStudioStateService; @@ -13,6 +16,8 @@ public final class StudioProjectSession implements AutoCloseable { private final ProjectLocalStudioStateService projectLocalStudioStateService; private final ProjectLocalStudioSetup projectLocalStudioSetup; private final StudioExecutionSessionService executionSessionService; + private final LspServerLifecycle lspServerLifecycle; + private final LspServerHandle lspServerHandle; private ProjectLocalStudioState projectLocalStudioState; private boolean closed; @@ -23,6 +28,8 @@ public final class StudioProjectSession implements AutoCloseable { new ProjectLocalStudioStateService(), ProjectLocalStudioSetup.defaults(), new StudioExecutionSessionService(), + null, + null, ProjectLocalStudioState.defaults()); } @@ -31,11 +38,15 @@ public final class StudioProjectSession implements AutoCloseable { final ProjectLocalStudioStateService projectLocalStudioStateService, final ProjectLocalStudioSetup projectLocalStudioSetup, final StudioExecutionSessionService executionSessionService, + final LspServerLifecycle lspServerLifecycle, + final LspServerHandle lspServerHandle, final ProjectLocalStudioState projectLocalStudioState) { this.projectReference = Objects.requireNonNull(projectReference, "projectReference"); this.projectLocalStudioStateService = Objects.requireNonNull(projectLocalStudioStateService, "projectLocalStudioStateService"); this.projectLocalStudioSetup = Objects.requireNonNull(projectLocalStudioSetup, "projectLocalStudioSetup"); this.executionSessionService = Objects.requireNonNull(executionSessionService, "executionSessionService"); + this.lspServerLifecycle = lspServerLifecycle; + this.lspServerHandle = lspServerHandle; this.projectLocalStudioState = Objects.requireNonNull(projectLocalStudioState, "projectLocalStudioState"); } @@ -55,6 +66,10 @@ public final class StudioProjectSession implements AutoCloseable { return executionSessionService; } + public LspServerHandle lspServerHandle() { + return lspServerHandle; + } + public void replaceProjectLocalStudioState(final ProjectLocalStudioState nextProjectLocalStudioState) { this.projectLocalStudioState = Objects.requireNonNull(nextProjectLocalStudioState, "nextProjectLocalStudioState"); } @@ -76,8 +91,12 @@ public final class StudioProjectSession implements AutoCloseable { failure = runtimeException; } try { - if (failure != null) { - throw failure; + shutdownLspServer(); + } catch (RuntimeException runtimeException) { + if (failure == null) { + failure = runtimeException; + } else { + failure.addSuppressed(runtimeException); } } finally { if (failure != null) { @@ -85,4 +104,12 @@ public final class StudioProjectSession implements AutoCloseable { } } } + + private void shutdownLspServer() { + if (lspServerLifecycle == null || lspServerHandle == null) { + return; + } + final LspProjectContext projectContext = lspServerHandle.project(); + lspServerLifecycle.shutdownServer(projectContext); + } } diff --git a/prometeu-studio/src/main/java/p/studio/projectsessions/StudioProjectSessionFactory.java b/prometeu-studio/src/main/java/p/studio/projectsessions/StudioProjectSessionFactory.java index 2dde9464..5258a7d3 100644 --- a/prometeu-studio/src/main/java/p/studio/projectsessions/StudioProjectSessionFactory.java +++ b/prometeu-studio/src/main/java/p/studio/projectsessions/StudioProjectSessionFactory.java @@ -1,5 +1,9 @@ package p.studio.projectsessions; +import p.studio.lsp.api.LspProjectContext; +import p.studio.lsp.api.LspServerBootRequest; +import p.studio.lsp.api.LspServerHandle; +import p.studio.lsp.api.LspServerLifecycle; import p.studio.execution.StudioExecutionSessionService; import p.studio.projectstate.ProjectLocalStudioSetupService; import p.studio.projectstate.ProjectLocalStudioStateService; @@ -10,27 +14,44 @@ import java.util.Objects; public final class StudioProjectSessionFactory { private final ProjectLocalStudioStateService projectLocalStudioStateService; private final ProjectLocalStudioSetupService projectLocalStudioSetupService; + private final LspServerLifecycle lspServerLifecycle; - public StudioProjectSessionFactory() { + public StudioProjectSessionFactory(final LspServerLifecycle lspServerLifecycle) { this( new ProjectLocalStudioStateService(), - new ProjectLocalStudioSetupService()); + new ProjectLocalStudioSetupService(), + Objects.requireNonNull(lspServerLifecycle, "lspServerLifecycle")); } StudioProjectSessionFactory( final ProjectLocalStudioStateService projectLocalStudioStateService, - final ProjectLocalStudioSetupService projectLocalStudioSetupService) { + final ProjectLocalStudioSetupService projectLocalStudioSetupService, + final LspServerLifecycle lspServerLifecycle) { this.projectLocalStudioStateService = Objects.requireNonNull(projectLocalStudioStateService, "projectLocalStudioStateService"); this.projectLocalStudioSetupService = Objects.requireNonNull(projectLocalStudioSetupService, "projectLocalStudioSetupService"); + this.lspServerLifecycle = Objects.requireNonNull(lspServerLifecycle, "lspServerLifecycle"); } public StudioProjectSession open(final ProjectReference projectReference) { final ProjectReference target = Objects.requireNonNull(projectReference, "projectReference"); + final var setup = projectLocalStudioSetupService.load(target); + final var state = projectLocalStudioStateService.load(target); + final LspProjectContext lspProjectContext = toLspProjectContext(target); + final LspServerHandle lspServerHandle = lspServerLifecycle.bootServer(LspServerBootRequest.defaults(lspProjectContext)); return new StudioProjectSession( target, projectLocalStudioStateService, - projectLocalStudioSetupService.load(target), + setup, new StudioExecutionSessionService(), - projectLocalStudioStateService.load(target)); + lspServerLifecycle, + lspServerHandle, + state); + } + + private static LspProjectContext toLspProjectContext(final ProjectReference projectReference) { + return new LspProjectContext( + projectReference.rootPath().toAbsolutePath().normalize().toString(), + projectReference.languageId(), + projectReference.rootPath()); } } diff --git a/prometeu-studio/src/main/java/p/studio/window/StudioWindowCoordinator.java b/prometeu-studio/src/main/java/p/studio/window/StudioWindowCoordinator.java index b0be78b2..be2b6321 100644 --- a/prometeu-studio/src/main/java/p/studio/window/StudioWindowCoordinator.java +++ b/prometeu-studio/src/main/java/p/studio/window/StudioWindowCoordinator.java @@ -37,7 +37,7 @@ public final class StudioWindowCoordinator { this.projectCatalogService = new ProjectCatalogService(resolveDefaultProjectsRoot()); this.knownProjectsService = new KnownProjectsService(resolveKnownProjectsStorage(), projectCatalogService); this.windowStateService = new WindowStateService(resolveWindowStateStorage()); - this.projectSessionFactory = new StudioProjectSessionFactory(); + this.projectSessionFactory = new StudioProjectSessionFactory(Container.lspServerLifecycle()); this.launcherView = new ProjectLauncherView( knownProjectsService, projectCatalogService, diff --git a/prometeu-studio/src/test/java/p/studio/projectsessions/StudioProjectSessionFactoryTest.java b/prometeu-studio/src/test/java/p/studio/projectsessions/StudioProjectSessionFactoryTest.java index 62cf61f5..6b2aa5fc 100644 --- a/prometeu-studio/src/test/java/p/studio/projectsessions/StudioProjectSessionFactoryTest.java +++ b/prometeu-studio/src/test/java/p/studio/projectsessions/StudioProjectSessionFactoryTest.java @@ -1,6 +1,10 @@ package p.studio.projectsessions; import org.junit.jupiter.api.Test; +import p.studio.lsp.api.LspProjectContext; +import p.studio.lsp.api.LspServerBootRequest; +import p.studio.lsp.api.LspServerHandle; +import p.studio.lsp.api.LspServerLifecycle; import p.studio.projectstate.ProjectLocalStudioSetup; import p.studio.projectstate.ProjectLocalStudioSetupService; import p.studio.projectstate.ProjectLocalStudioState; @@ -10,16 +14,20 @@ import p.studio.projects.ProjectReference; import java.nio.file.Path; import static org.junit.jupiter.api.Assertions.assertEquals; +import static org.junit.jupiter.api.Assertions.assertNotNull; import static org.junit.jupiter.api.Assertions.assertSame; +import static org.junit.jupiter.api.Assertions.assertThrows; final class StudioProjectSessionFactoryTest { @Test - void openCreatesProjectSessionWithoutLegacyEditorServices() { + void openCreatesProjectSessionAndBootsLspServer() { final RecordingProjectLocalStudioStateService stateService = new RecordingProjectLocalStudioStateService(); final RecordingProjectLocalStudioSetupService setupService = new RecordingProjectLocalStudioSetupService(); + final RecordingLspServerLifecycle lspServerLifecycle = new RecordingLspServerLifecycle(); final StudioProjectSessionFactory sessionFactory = new StudioProjectSessionFactory( stateService, - setupService); + setupService, + lspServerLifecycle); final ProjectReference projectReference = new ProjectReference( "Example", "1.0.0", @@ -35,6 +43,29 @@ final class StudioProjectSessionFactoryTest { assertEquals("IDLE", session.executionSession().snapshot().state().name()); assertSame(projectReference, stateService.loadedProjectReference); assertSame(projectReference, setupService.loadedProjectReference); + assertNotNull(session.lspServerHandle()); + assertEquals(1, lspServerLifecycle.bootCalls); + assertEquals(projectReference.languageId(), lspServerLifecycle.lastRequest.project().languageId()); + assertEquals(projectReference.rootPath().toAbsolutePath().normalize(), lspServerLifecycle.lastRequest.project().projectRoot()); + } + + @Test + void openSurfacesLspBootFailure() { + final RecordingProjectLocalStudioStateService stateService = new RecordingProjectLocalStudioStateService(); + final RecordingProjectLocalStudioSetupService setupService = new RecordingProjectLocalStudioSetupService(); + final StudioProjectSessionFactory sessionFactory = new StudioProjectSessionFactory( + stateService, + setupService, + new FailingLspServerLifecycle()); + + final IllegalStateException failure = assertThrows(IllegalStateException.class, () -> sessionFactory.open(new ProjectReference( + "Example", + "1.0.0", + "pbs", + 1, + Path.of("/tmp/example")))); + + assertEquals("boom", failure.getMessage()); } private static final class RecordingProjectLocalStudioStateService extends ProjectLocalStudioStateService { @@ -63,4 +94,33 @@ final class StudioProjectSessionFactoryTest { return loadedSetup; } } + + private static final class RecordingLspServerLifecycle implements LspServerLifecycle { + private int bootCalls; + private LspServerBootRequest lastRequest; + + @Override + public LspServerHandle bootServer(final LspServerBootRequest request) { + bootCalls++; + lastRequest = request; + return new LspServerHandle( + request.project(), + new p.studio.lsp.api.LspServerEndpoint("127.0.0.1", request.configuration().port())); + } + + @Override + public void shutdownServer(final LspProjectContext project) { + } + } + + private static final class FailingLspServerLifecycle implements LspServerLifecycle { + @Override + public LspServerHandle bootServer(final LspServerBootRequest request) { + throw new IllegalStateException("boom"); + } + + @Override + public void shutdownServer(final LspProjectContext project) { + } + } } diff --git a/prometeu-studio/src/test/java/p/studio/projectsessions/StudioProjectSessionTest.java b/prometeu-studio/src/test/java/p/studio/projectsessions/StudioProjectSessionTest.java index 87eca3bb..f9a8eb8b 100644 --- a/prometeu-studio/src/test/java/p/studio/projectsessions/StudioProjectSessionTest.java +++ b/prometeu-studio/src/test/java/p/studio/projectsessions/StudioProjectSessionTest.java @@ -2,6 +2,9 @@ package p.studio.projectsessions; import org.junit.jupiter.api.Test; import p.studio.execution.StudioExecutionSessionService; +import p.studio.lsp.api.LspProjectContext; +import p.studio.lsp.api.LspServerHandle; +import p.studio.lsp.api.LspServerLifecycle; import p.studio.projectstate.ProjectLocalStudioSetup; import p.studio.projectstate.ProjectLocalStudioState; import p.studio.projectstate.ProjectLocalStudioStateService; @@ -21,6 +24,8 @@ final class StudioProjectSessionTest { stateService, ProjectLocalStudioSetup.defaults(), new StudioExecutionSessionService(), + null, + null, ProjectLocalStudioState.defaults()); session.close(); @@ -38,6 +43,8 @@ final class StudioProjectSessionTest { stateService, ProjectLocalStudioSetup.defaults(), new StudioExecutionSessionService(), + null, + null, ProjectLocalStudioState.defaults()); final ProjectLocalStudioState nextState = ProjectLocalStudioState.defaults() .withOpenShellState(new ProjectLocalStudioState.OpenShellState("ASSETS")); @@ -48,6 +55,29 @@ final class StudioProjectSessionTest { assertSame(nextState, stateService.savedState); } + @Test + void closeShutsDownLspServerOnlyOnce() { + final RecordingProjectLocalStudioStateService stateService = new RecordingProjectLocalStudioStateService(); + final RecordingLspServerLifecycle lspServerLifecycle = new RecordingLspServerLifecycle(); + final LspServerHandle lspServerHandle = new LspServerHandle( + new LspProjectContext("demo", "pbs", Path.of("/tmp/example")), + new p.studio.lsp.api.LspServerEndpoint("127.0.0.1", 7777)); + final StudioProjectSession session = new StudioProjectSession( + projectReference(), + stateService, + ProjectLocalStudioSetup.defaults(), + new StudioExecutionSessionService(), + lspServerLifecycle, + lspServerHandle, + ProjectLocalStudioState.defaults()); + + session.close(); + session.close(); + + assertEquals(1, lspServerLifecycle.shutdownCalls); + assertEquals(lspServerHandle.project(), lspServerLifecycle.lastProject); + } + private ProjectReference projectReference() { return new ProjectReference("Example", "1.0.0", "pbs", 1, Path.of("/tmp/example")); } @@ -64,4 +94,20 @@ final class StudioProjectSessionTest { savedState = state; } } + + private static final class RecordingLspServerLifecycle implements LspServerLifecycle { + private int shutdownCalls; + private LspProjectContext lastProject; + + @Override + public LspServerHandle bootServer(final p.studio.lsp.api.LspServerBootRequest request) { + throw new UnsupportedOperationException(); + } + + @Override + public void shutdownServer(final LspProjectContext project) { + shutdownCalls++; + lastProject = project; + } + } } -- 2.47.2 From f6774ef5685a43a1501601e256ec6c5b24c0af61 Mon Sep 17 00:00:00 2001 From: bQUARKz Date: Tue, 5 May 2026 15:57:27 +0100 Subject: [PATCH 08/37] implements PLN-0067 --- discussion/index.ndjson | 2 +- ...ompiler-backed-dumb-lsp-server-baseline.md | 14 +- .../v1/compiler/BaselineDocumentAnalysis.java | 12 ++ .../v1/compiler/BaselineDocumentIssue.java | 29 ++++ .../studio/lsp/v1/compiler/BaselineHover.java | 15 ++ .../v1/compiler/BaselineIssueSeverity.java | 7 + .../compiler/BaselineServerDescription.java | 24 ++++ .../CompilerLanguageServiceBridge.java | 62 +++++++- .../v1/compiler/LanguageServiceBridge.java | 13 ++ .../v1/protocol/PrometeuLanguageServer.java | 35 ++--- .../protocol/PrometeuTextDocumentService.java | 69 ++++----- .../mapping/Lsp4jProtocolMessageMapper.java | 78 ++++++++++ .../mapping/ProtocolMessageMapper.java | 21 +++ .../mapping/ProtocolServerProfile.java | 11 -- .../mapping/ServerCapabilitiesMapper.java | 27 ---- .../CompilerLanguageServiceBridgeTest.java | 29 ++++ .../protocol/PrometeuLanguageServerTest.java | 116 +++++++++++++++ .../PrometeuTextDocumentServiceTest.java | 136 ++++++++++++++++++ 18 files changed, 597 insertions(+), 103 deletions(-) create mode 100644 prometeu-lsp/prometeu-lsp-v1/src/main/java/p/studio/lsp/v1/compiler/BaselineDocumentAnalysis.java create mode 100644 prometeu-lsp/prometeu-lsp-v1/src/main/java/p/studio/lsp/v1/compiler/BaselineDocumentIssue.java create mode 100644 prometeu-lsp/prometeu-lsp-v1/src/main/java/p/studio/lsp/v1/compiler/BaselineHover.java create mode 100644 prometeu-lsp/prometeu-lsp-v1/src/main/java/p/studio/lsp/v1/compiler/BaselineIssueSeverity.java create mode 100644 prometeu-lsp/prometeu-lsp-v1/src/main/java/p/studio/lsp/v1/compiler/BaselineServerDescription.java create mode 100644 prometeu-lsp/prometeu-lsp-v1/src/main/java/p/studio/lsp/v1/compiler/LanguageServiceBridge.java create mode 100644 prometeu-lsp/prometeu-lsp-v1/src/main/java/p/studio/lsp/v1/protocol/mapping/Lsp4jProtocolMessageMapper.java create mode 100644 prometeu-lsp/prometeu-lsp-v1/src/main/java/p/studio/lsp/v1/protocol/mapping/ProtocolMessageMapper.java delete mode 100644 prometeu-lsp/prometeu-lsp-v1/src/main/java/p/studio/lsp/v1/protocol/mapping/ProtocolServerProfile.java delete mode 100644 prometeu-lsp/prometeu-lsp-v1/src/main/java/p/studio/lsp/v1/protocol/mapping/ServerCapabilitiesMapper.java create mode 100644 prometeu-lsp/prometeu-lsp-v1/src/test/java/p/studio/lsp/v1/compiler/CompilerLanguageServiceBridgeTest.java create mode 100644 prometeu-lsp/prometeu-lsp-v1/src/test/java/p/studio/lsp/v1/protocol/PrometeuLanguageServerTest.java create mode 100644 prometeu-lsp/prometeu-lsp-v1/src/test/java/p/studio/lsp/v1/protocol/PrometeuTextDocumentServiceTest.java diff --git a/discussion/index.ndjson b/discussion/index.ndjson index 105c34f9..c862806e 100644 --- a/discussion/index.ndjson +++ b/discussion/index.ndjson @@ -1,5 +1,5 @@ {"type":"meta","next_id":{"DSC":33,"AGD":36,"DEC":33,"PLN":68,"LSN":47,"CLSN":1}} -{"type":"discussion","id":"DSC-0032","status":"in_progress","ticket":"studio-new-lsp-api-and-v1-boundary","title":"Novo boundary entre lsp-api, lsp-v1 e a extensao VS Code","created_at":"2026-05-05","updated_at":"2026-05-05","tags":["studio","lsp","vscode","protocol","api","boundary"],"agendas":[{"id":"AGD-0035","file":"AGD-0035-studio-new-lsp-api-and-v1-boundary.md","status":"accepted","created_at":"2026-05-05","updated_at":"2026-05-05"}],"decisions":[{"id":"DEC-0032","file":"DEC-0032-studio-new-lsp-api-and-v1-boundary.md","status":"accepted","created_at":"2026-05-05","updated_at":"2026-05-05","ref_agenda":"AGD-0035"}],"plans":[{"id":"PLN-0065","file":"PLN-0065-lsp-boundary-and-module-scaffolding.md","status":"done","created_at":"2026-05-05","updated_at":"2026-05-05","ref_decisions":["DEC-0032"]},{"id":"PLN-0066","file":"PLN-0066-project-scoped-lsp-server-lifecycle-in-studio.md","status":"done","created_at":"2026-05-05","updated_at":"2026-05-05","ref_decisions":["DEC-0032"]},{"id":"PLN-0067","file":"PLN-0067-compiler-backed-dumb-lsp-server-baseline.md","status":"open","created_at":"2026-05-05","updated_at":"2026-05-05","ref_decisions":["DEC-0032"]}],"lessons":[]} +{"type":"discussion","id":"DSC-0032","status":"in_progress","ticket":"studio-new-lsp-api-and-v1-boundary","title":"Novo boundary entre lsp-api, lsp-v1 e a extensao VS Code","created_at":"2026-05-05","updated_at":"2026-05-05","tags":["studio","lsp","vscode","protocol","api","boundary"],"agendas":[{"id":"AGD-0035","file":"AGD-0035-studio-new-lsp-api-and-v1-boundary.md","status":"accepted","created_at":"2026-05-05","updated_at":"2026-05-05"}],"decisions":[{"id":"DEC-0032","file":"DEC-0032-studio-new-lsp-api-and-v1-boundary.md","status":"accepted","created_at":"2026-05-05","updated_at":"2026-05-05","ref_agenda":"AGD-0035"}],"plans":[{"id":"PLN-0065","file":"PLN-0065-lsp-boundary-and-module-scaffolding.md","status":"done","created_at":"2026-05-05","updated_at":"2026-05-05","ref_decisions":["DEC-0032"]},{"id":"PLN-0066","file":"PLN-0066-project-scoped-lsp-server-lifecycle-in-studio.md","status":"done","created_at":"2026-05-05","updated_at":"2026-05-05","ref_decisions":["DEC-0032"]},{"id":"PLN-0067","file":"PLN-0067-compiler-backed-dumb-lsp-server-baseline.md","status":"done","created_at":"2026-05-05","updated_at":"2026-05-05","ref_decisions":["DEC-0032"]}],"lessons":[]} {"type":"discussion","id":"DSC-0031","status":"in_progress","ticket":"studio-editor-workspace-cleanup","title":"Limpeza completa do Workspace Editor do Studio e remoção dos acoplamentos legados","created_at":"2026-05-05","updated_at":"2026-05-05","tags":["studio","editor","cleanup","vfs","lsp","migration"],"agendas":[{"id":"AGD-0034","file":"AGD-0034-vscode-editor-migration-feasibility.md","status":"accepted","created_at":"2026-05-05","updated_at":"2026-05-05"}],"decisions":[{"id":"DEC-0031","file":"DEC-0031-studio-editor-workspace-cleanup.md","status":"in_progress","created_at":"2026-05-05","updated_at":"2026-05-05","ref_agenda":"AGD-0034"}],"plans":[{"id":"PLN-0062","file":"PLN-0062-shell-session-and-state-cleanup-after-editor-removal.md","status":"done","created_at":"2026-05-05","updated_at":"2026-05-05","ref_decisions":["DEC-0031"]},{"id":"PLN-0063","file":"PLN-0063-legacy-lsp-and-vfs-module-removal-with-runtime-preservation.md","status":"done","created_at":"2026-05-05","updated_at":"2026-05-05","ref_decisions":["DEC-0031"]},{"id":"PLN-0064","file":"PLN-0064-normative-test-and-lesson-cleanup-for-editor-stack-removal.md","status":"done","created_at":"2026-05-05","updated_at":"2026-05-05","ref_decisions":["DEC-0031"]}],"lessons":[]} {"type":"discussion","id":"DSC-0030","status":"done","ticket":"studio-scene-pack-runtime-binary-contract","title":"Studio scene pack contract for runtime SCENE binary payload","created_at":"2026-04-24","updated_at":"2026-05-01","tags":["studio","packer","runtime","scene","asset-pack","binary-format","tiled"],"agendas":[],"decisions":[],"plans":[],"lessons":[{"id":"LSN-0046","file":"discussion/lessons/DSC-0030-studio-scene-pack-runtime-binary-contract/LSN-0046-canonical-scene-owns-editorial-truth-while-pack-stays-request-driven.md","status":"done","created_at":"2026-05-01","updated_at":"2026-05-01"}]} {"type":"discussion","id":"DSC-0029","status":"done","ticket":"studio-frame-composer-syscall-and-sprite-alignment","title":"Studio Alignment with Runtime FrameComposer Syscalls and Sprite Composition","created_at":"2026-04-18","updated_at":"2026-04-18","tags":["studio","compiler","pbs","stdlib","runtime-alignment","abi","syscall","frame-composer","sprites"],"agendas":[],"decisions":[],"plans":[],"lessons":[{"id":"LSN-0041","file":"discussion/lessons/DSC-0029-studio-frame-composer-syscall-and-sprite-alignment/LSN-0041-composer-must-own-public-sprite-composition.md","status":"done","created_at":"2026-04-18","updated_at":"2026-04-18"}]} diff --git a/discussion/workflow/plans/PLN-0067-compiler-backed-dumb-lsp-server-baseline.md b/discussion/workflow/plans/PLN-0067-compiler-backed-dumb-lsp-server-baseline.md index d320f1f8..b9e652ce 100644 --- a/discussion/workflow/plans/PLN-0067-compiler-backed-dumb-lsp-server-baseline.md +++ b/discussion/workflow/plans/PLN-0067-compiler-backed-dumb-lsp-server-baseline.md @@ -2,9 +2,9 @@ id: PLN-0067 ticket: studio-new-lsp-api-and-v1-boundary title: Compiler-Backed Dumb LSP Server Baseline -status: open +status: done created: 2026-05-05 -completed: +completed: 2026-05-05 tags: [studio, lsp, compiler, baseline, protocol, vscode] --- @@ -81,11 +81,11 @@ Establish a maintainable, compiler-backed baseline inside `lsp-v1` that keeps th ## Acceptance Criteria -- [ ] `lsp-v1` talks to `compiler` through explicit bridge services. -- [ ] The baseline server behavior remains intentionally simple but structurally clean. -- [ ] At least one minimal end-to-end capability slice proves the final layering. -- [ ] The extension can still connect over TCP without protocol regressions. -- [ ] Temporary semantic limits are explicit in tests and code structure. +- [x] `lsp-v1` talks to `compiler` through explicit bridge services. +- [x] The baseline server behavior remains intentionally simple but structurally clean. +- [x] At least one minimal end-to-end capability slice proves the final layering. +- [x] The extension can still connect over TCP without protocol regressions. +- [x] Temporary semantic limits are explicit in tests and code structure. ## Dependencies diff --git a/prometeu-lsp/prometeu-lsp-v1/src/main/java/p/studio/lsp/v1/compiler/BaselineDocumentAnalysis.java b/prometeu-lsp/prometeu-lsp-v1/src/main/java/p/studio/lsp/v1/compiler/BaselineDocumentAnalysis.java new file mode 100644 index 00000000..edb457fe --- /dev/null +++ b/prometeu-lsp/prometeu-lsp-v1/src/main/java/p/studio/lsp/v1/compiler/BaselineDocumentAnalysis.java @@ -0,0 +1,12 @@ +package p.studio.lsp.v1.compiler; + +import java.util.List; +import java.util.Objects; + +public record BaselineDocumentAnalysis( + List issues) { + + public BaselineDocumentAnalysis { + issues = List.copyOf(Objects.requireNonNull(issues, "issues")); + } +} diff --git a/prometeu-lsp/prometeu-lsp-v1/src/main/java/p/studio/lsp/v1/compiler/BaselineDocumentIssue.java b/prometeu-lsp/prometeu-lsp-v1/src/main/java/p/studio/lsp/v1/compiler/BaselineDocumentIssue.java new file mode 100644 index 00000000..6b19dc8d --- /dev/null +++ b/prometeu-lsp/prometeu-lsp-v1/src/main/java/p/studio/lsp/v1/compiler/BaselineDocumentIssue.java @@ -0,0 +1,29 @@ +package p.studio.lsp.v1.compiler; + +import java.util.Objects; + +public record BaselineDocumentIssue( + int startLine, + int startCharacter, + int endLine, + int endCharacter, + BaselineIssueSeverity severity, + String source, + String message) { + + public BaselineDocumentIssue { + severity = Objects.requireNonNull(severity, "severity"); + source = requireText(source, "source"); + message = requireText(message, "message"); + } + + private static String requireText( + final String value, + final String field) { + final String candidate = Objects.requireNonNull(value, field).trim(); + if (candidate.isEmpty()) { + throw new IllegalArgumentException(field + " must not be blank"); + } + return candidate; + } +} diff --git a/prometeu-lsp/prometeu-lsp-v1/src/main/java/p/studio/lsp/v1/compiler/BaselineHover.java b/prometeu-lsp/prometeu-lsp-v1/src/main/java/p/studio/lsp/v1/compiler/BaselineHover.java new file mode 100644 index 00000000..46efc4d2 --- /dev/null +++ b/prometeu-lsp/prometeu-lsp-v1/src/main/java/p/studio/lsp/v1/compiler/BaselineHover.java @@ -0,0 +1,15 @@ +package p.studio.lsp.v1.compiler; + +import java.util.Objects; + +public record BaselineHover( + String markdown) { + + public BaselineHover { + final String candidate = Objects.requireNonNull(markdown, "markdown").trim(); + if (candidate.isEmpty()) { + throw new IllegalArgumentException("markdown must not be blank"); + } + markdown = candidate; + } +} diff --git a/prometeu-lsp/prometeu-lsp-v1/src/main/java/p/studio/lsp/v1/compiler/BaselineIssueSeverity.java b/prometeu-lsp/prometeu-lsp-v1/src/main/java/p/studio/lsp/v1/compiler/BaselineIssueSeverity.java new file mode 100644 index 00000000..f6f7caa8 --- /dev/null +++ b/prometeu-lsp/prometeu-lsp-v1/src/main/java/p/studio/lsp/v1/compiler/BaselineIssueSeverity.java @@ -0,0 +1,7 @@ +package p.studio.lsp.v1.compiler; + +public enum BaselineIssueSeverity { + INFORMATION, + WARNING, + ERROR +} diff --git a/prometeu-lsp/prometeu-lsp-v1/src/main/java/p/studio/lsp/v1/compiler/BaselineServerDescription.java b/prometeu-lsp/prometeu-lsp-v1/src/main/java/p/studio/lsp/v1/compiler/BaselineServerDescription.java new file mode 100644 index 00000000..dab48834 --- /dev/null +++ b/prometeu-lsp/prometeu-lsp-v1/src/main/java/p/studio/lsp/v1/compiler/BaselineServerDescription.java @@ -0,0 +1,24 @@ +package p.studio.lsp.v1.compiler; + +import java.util.Objects; + +public record BaselineServerDescription( + String name, + String version, + boolean hoverSupported) { + + public BaselineServerDescription { + name = requireText(name, "name"); + version = requireText(version, "version"); + } + + private static String requireText( + final String value, + final String field) { + final String candidate = Objects.requireNonNull(value, field).trim(); + if (candidate.isEmpty()) { + throw new IllegalArgumentException(field + " must not be blank"); + } + return candidate; + } +} diff --git a/prometeu-lsp/prometeu-lsp-v1/src/main/java/p/studio/lsp/v1/compiler/CompilerLanguageServiceBridge.java b/prometeu-lsp/prometeu-lsp-v1/src/main/java/p/studio/lsp/v1/compiler/CompilerLanguageServiceBridge.java index 6495745b..8021ec50 100644 --- a/prometeu-lsp/prometeu-lsp-v1/src/main/java/p/studio/lsp/v1/compiler/CompilerLanguageServiceBridge.java +++ b/prometeu-lsp/prometeu-lsp-v1/src/main/java/p/studio/lsp/v1/compiler/CompilerLanguageServiceBridge.java @@ -1,10 +1,11 @@ package p.studio.lsp.v1.compiler; import p.studio.compiler.workspaces.BuilderPipelineService; +import p.studio.lsp.api.LspProjectContext; import java.util.Objects; -public final class CompilerLanguageServiceBridge { +public final class CompilerLanguageServiceBridge implements LanguageServiceBridge { private final BuilderPipelineService builderPipelineService; public CompilerLanguageServiceBridge() { @@ -18,4 +19,63 @@ public final class CompilerLanguageServiceBridge { public BuilderPipelineService builderPipelineService() { return builderPipelineService; } + + @Override + public BaselineServerDescription describeServer(final LspProjectContext project) { + Objects.requireNonNull(project, "project"); + return new BaselineServerDescription( + "Prometeu Studio LSP", + "0.1.0", + true); + } + + @Override + public BaselineDocumentAnalysis analyzeDocument( + final LspProjectContext project, + final String documentUri, + final String text) { + Objects.requireNonNull(project, "project"); + // Wave 1 keeps responses intentionally synthetic while hardening the bridge boundary. + final String message = "Compiler-backed baseline via " + builderPipelineService.getClass().getSimpleName(); + return new BaselineDocumentAnalysis(java.util.List.of(new BaselineDocumentIssue( + 0, + 0, + 0, + Math.max(1, firstLineLength(text)), + BaselineIssueSeverity.INFORMATION, + "Prometeu Studio", + message))); + } + + @Override + public BaselineHover hover( + final LspProjectContext project, + final String documentUri, + final int line, + final int character) { + Objects.requireNonNull(project, "project"); + return new BaselineHover(""" + **Prometeu Studio LSP** + + Compiler-backed baseline. + + Semantic enrichment will be layered later. + """); + } + + @Override + public String onSave( + final LspProjectContext project, + final String documentUri) { + Objects.requireNonNull(project, "project"); + return "Prometeu Studio saw save: " + documentUri; + } + + private int firstLineLength(final String text) { + if (text == null || text.isEmpty()) { + return 1; + } + final int newline = text.indexOf('\n'); + return newline < 0 ? text.length() : newline; + } } diff --git a/prometeu-lsp/prometeu-lsp-v1/src/main/java/p/studio/lsp/v1/compiler/LanguageServiceBridge.java b/prometeu-lsp/prometeu-lsp-v1/src/main/java/p/studio/lsp/v1/compiler/LanguageServiceBridge.java new file mode 100644 index 00000000..689d6fd2 --- /dev/null +++ b/prometeu-lsp/prometeu-lsp-v1/src/main/java/p/studio/lsp/v1/compiler/LanguageServiceBridge.java @@ -0,0 +1,13 @@ +package p.studio.lsp.v1.compiler; + +import p.studio.lsp.api.LspProjectContext; + +public interface LanguageServiceBridge { + BaselineServerDescription describeServer(LspProjectContext project); + + BaselineDocumentAnalysis analyzeDocument(LspProjectContext project, String documentUri, String text); + + BaselineHover hover(LspProjectContext project, String documentUri, int line, int character); + + String onSave(LspProjectContext project, String documentUri); +} diff --git a/prometeu-lsp/prometeu-lsp-v1/src/main/java/p/studio/lsp/v1/protocol/PrometeuLanguageServer.java b/prometeu-lsp/prometeu-lsp-v1/src/main/java/p/studio/lsp/v1/protocol/PrometeuLanguageServer.java index d10f225b..3cf5b036 100644 --- a/prometeu-lsp/prometeu-lsp-v1/src/main/java/p/studio/lsp/v1/protocol/PrometeuLanguageServer.java +++ b/prometeu-lsp/prometeu-lsp-v1/src/main/java/p/studio/lsp/v1/protocol/PrometeuLanguageServer.java @@ -8,16 +8,17 @@ import org.eclipse.lsp4j.services.TextDocumentService; import org.eclipse.lsp4j.services.WorkspaceService; import p.studio.lsp.api.LspProjectContext; import p.studio.lsp.v1.compiler.CompilerLanguageServiceBridge; -import p.studio.lsp.v1.protocol.mapping.ProtocolServerProfile; -import p.studio.lsp.v1.protocol.mapping.ServerCapabilitiesMapper; +import p.studio.lsp.v1.compiler.LanguageServiceBridge; +import p.studio.lsp.v1.protocol.mapping.Lsp4jProtocolMessageMapper; +import p.studio.lsp.v1.protocol.mapping.ProtocolMessageMapper; import java.util.Objects; import java.util.concurrent.CompletableFuture; public final class PrometeuLanguageServer implements LanguageServer, LanguageClientAware { private final LspProjectContext project; - private final CompilerLanguageServiceBridge compilerBridge; - private final ServerCapabilitiesMapper capabilitiesMapper; + private final LanguageServiceBridge languageServiceBridge; + private final ProtocolMessageMapper protocolMessageMapper; private final TextDocumentService textDocumentService; private final WorkspaceService workspaceService; private volatile LanguageClient client; @@ -28,21 +29,23 @@ public final class PrometeuLanguageServer implements LanguageServer, LanguageCli final CompilerLanguageServiceBridge compilerBridge) { this(project, compilerBridge, - new ServerCapabilitiesMapper(), - new PrometeuTextDocumentService(), + new Lsp4jProtocolMessageMapper(), + null, new PrometeuWorkspaceService()); } PrometeuLanguageServer( final LspProjectContext project, - final CompilerLanguageServiceBridge compilerBridge, - final ServerCapabilitiesMapper capabilitiesMapper, + final LanguageServiceBridge languageServiceBridge, + final ProtocolMessageMapper protocolMessageMapper, final TextDocumentService textDocumentService, final WorkspaceService workspaceService) { this.project = Objects.requireNonNull(project, "project"); - this.compilerBridge = Objects.requireNonNull(compilerBridge, "compilerBridge"); - this.capabilitiesMapper = Objects.requireNonNull(capabilitiesMapper, "capabilitiesMapper"); - this.textDocumentService = Objects.requireNonNull(textDocumentService, "textDocumentService"); + this.languageServiceBridge = Objects.requireNonNull(languageServiceBridge, "languageServiceBridge"); + this.protocolMessageMapper = Objects.requireNonNull(protocolMessageMapper, "protocolMessageMapper"); + this.textDocumentService = textDocumentService != null + ? textDocumentService + : new PrometeuTextDocumentService(project, languageServiceBridge, protocolMessageMapper); this.workspaceService = Objects.requireNonNull(workspaceService, "workspaceService"); } @@ -56,8 +59,8 @@ public final class PrometeuLanguageServer implements LanguageServer, LanguageCli @Override public CompletableFuture initialize(final InitializeParams params) { - final ProtocolServerProfile profile = ProtocolServerProfile.defaults(); - return CompletableFuture.completedFuture(capabilitiesMapper.map(profile)); + return CompletableFuture.completedFuture(protocolMessageMapper.mapInitializeResult( + languageServiceBridge.describeServer(project))); } @Override @@ -66,8 +69,7 @@ public final class PrometeuLanguageServer implements LanguageServer, LanguageCli if (currentClient == null) { return; } - currentClient.logMessage(new MessageParams( - MessageType.Info, + currentClient.logMessage(protocolMessageMapper.mapInfoMessage( "Prometeu Studio LSP connected for project " + project.projectKey())); } @@ -82,8 +84,7 @@ public final class PrometeuLanguageServer implements LanguageServer, LanguageCli if (!shutdownRequested) { final LanguageClient currentClient = client; if (currentClient != null) { - currentClient.logMessage(new MessageParams( - MessageType.Warning, + currentClient.logMessage(new MessageParams(MessageType.Warning, "Prometeu Studio LSP received exit before shutdown")); } } diff --git a/prometeu-lsp/prometeu-lsp-v1/src/main/java/p/studio/lsp/v1/protocol/PrometeuTextDocumentService.java b/prometeu-lsp/prometeu-lsp-v1/src/main/java/p/studio/lsp/v1/protocol/PrometeuTextDocumentService.java index 952e2772..c81edb55 100644 --- a/prometeu-lsp/prometeu-lsp-v1/src/main/java/p/studio/lsp/v1/protocol/PrometeuTextDocumentService.java +++ b/prometeu-lsp/prometeu-lsp-v1/src/main/java/p/studio/lsp/v1/protocol/PrometeuTextDocumentService.java @@ -3,20 +3,35 @@ package p.studio.lsp.v1.protocol; import org.eclipse.lsp4j.*; import org.eclipse.lsp4j.services.LanguageClient; import org.eclipse.lsp4j.services.TextDocumentService; +import p.studio.lsp.api.LspProjectContext; +import p.studio.lsp.v1.compiler.LanguageServiceBridge; +import p.studio.lsp.v1.protocol.mapping.ProtocolMessageMapper; -import java.util.List; +import java.util.Objects; import java.util.concurrent.CompletableFuture; public final class PrometeuTextDocumentService implements TextDocumentService { + private final LspProjectContext project; + private final LanguageServiceBridge languageServiceBridge; + private final ProtocolMessageMapper protocolMessageMapper; private volatile LanguageClient client; + public PrometeuTextDocumentService( + final LspProjectContext project, + final LanguageServiceBridge languageServiceBridge, + final ProtocolMessageMapper protocolMessageMapper) { + this.project = Objects.requireNonNull(project, "project"); + this.languageServiceBridge = Objects.requireNonNull(languageServiceBridge, "languageServiceBridge"); + this.protocolMessageMapper = Objects.requireNonNull(protocolMessageMapper, "protocolMessageMapper"); + } + void connect(final LanguageClient client) { this.client = client; } @Override public void didOpen(final DidOpenTextDocumentParams params) { - publishHelloDiagnostic(params.getTextDocument().getUri(), params.getTextDocument().getText()); + publishAnalysis(params.getTextDocument().getUri(), params.getTextDocument().getText()); } @Override @@ -24,7 +39,7 @@ public final class PrometeuTextDocumentService implements TextDocumentService { final String text = params.getContentChanges().isEmpty() ? "" : params.getContentChanges().getFirst().getText(); - publishHelloDiagnostic(params.getTextDocument().getUri(), text); + publishAnalysis(params.getTextDocument().getUri(), text); } @Override @@ -33,7 +48,7 @@ public final class PrometeuTextDocumentService implements TextDocumentService { if (currentClient == null) { return; } - currentClient.publishDiagnostics(new PublishDiagnosticsParams(params.getTextDocument().getUri(), List.of())); + currentClient.publishDiagnostics(protocolMessageMapper.emptyDiagnostics(params.getTextDocument().getUri())); } @Override @@ -42,52 +57,28 @@ public final class PrometeuTextDocumentService implements TextDocumentService { if (currentClient == null) { return; } - currentClient.logMessage(new MessageParams( - MessageType.Info, - "Prometeu Studio saw save: " + params.getTextDocument().getUri())); + currentClient.logMessage(protocolMessageMapper.mapInfoMessage( + languageServiceBridge.onSave(project, params.getTextDocument().getUri()))); } @Override public CompletableFuture hover(final HoverParams params) { - final MarkupContent content = new MarkupContent(); - content.setKind(MarkupKind.MARKDOWN); - content.setValue(""" - **Prometeu Studio LSP** - - Structured baseline server. - - Semantic enrichment will be layered later. - """); - - final Hover hover = new Hover(); - hover.setContents(content); - return CompletableFuture.completedFuture(hover); + return CompletableFuture.completedFuture(protocolMessageMapper.mapHover(languageServiceBridge.hover( + project, + params.getTextDocument().getUri(), + params.getPosition().getLine(), + params.getPosition().getCharacter()))); } - private void publishHelloDiagnostic( + private void publishAnalysis( final String uri, final String text) { final LanguageClient currentClient = client; if (currentClient == null) { return; } - - final Diagnostic diagnostic = new Diagnostic(); - diagnostic.setRange(new Range( - new Position(0, 0), - new Position(0, Math.max(1, firstLineLength(text))))); - diagnostic.setSeverity(DiagnosticSeverity.Information); - diagnostic.setSource("Prometeu Studio"); - diagnostic.setMessage("Structured baseline LSP response"); - - currentClient.publishDiagnostics(new PublishDiagnosticsParams(uri, List.of(diagnostic))); - } - - private int firstLineLength(final String text) { - if (text == null || text.isEmpty()) { - return 1; - } - final int newline = text.indexOf('\n'); - return newline < 0 ? text.length() : newline; + currentClient.publishDiagnostics(protocolMessageMapper.mapDiagnostics( + uri, + languageServiceBridge.analyzeDocument(project, uri, text))); } } diff --git a/prometeu-lsp/prometeu-lsp-v1/src/main/java/p/studio/lsp/v1/protocol/mapping/Lsp4jProtocolMessageMapper.java b/prometeu-lsp/prometeu-lsp-v1/src/main/java/p/studio/lsp/v1/protocol/mapping/Lsp4jProtocolMessageMapper.java new file mode 100644 index 00000000..a6cee146 --- /dev/null +++ b/prometeu-lsp/prometeu-lsp-v1/src/main/java/p/studio/lsp/v1/protocol/mapping/Lsp4jProtocolMessageMapper.java @@ -0,0 +1,78 @@ +package p.studio.lsp.v1.protocol.mapping; + +import org.eclipse.lsp4j.*; +import p.studio.lsp.v1.compiler.*; + +import java.util.List; + +public final class Lsp4jProtocolMessageMapper implements ProtocolMessageMapper { + @Override + public InitializeResult mapInitializeResult(final BaselineServerDescription description) { + final ServerCapabilities capabilities = new ServerCapabilities(); + + final TextDocumentSyncOptions syncOptions = new TextDocumentSyncOptions(); + syncOptions.setOpenClose(true); + syncOptions.setChange(TextDocumentSyncKind.Full); + + final SaveOptions saveOptions = new SaveOptions(); + saveOptions.setIncludeText(true); + syncOptions.setSave(saveOptions); + + capabilities.setTextDocumentSync(syncOptions); + capabilities.setHoverProvider(description.hoverSupported()); + + final InitializeResult result = new InitializeResult(capabilities); + final ServerInfo serverInfo = new ServerInfo(); + serverInfo.setName(description.name()); + serverInfo.setVersion(description.version()); + result.setServerInfo(serverInfo); + return result; + } + + @Override + public PublishDiagnosticsParams mapDiagnostics( + final String uri, + final BaselineDocumentAnalysis analysis) { + return new PublishDiagnosticsParams(uri, analysis.issues().stream().map(this::mapDiagnostic).toList()); + } + + @Override + public PublishDiagnosticsParams emptyDiagnostics(final String uri) { + return new PublishDiagnosticsParams(uri, List.of()); + } + + @Override + public Hover mapHover(final BaselineHover hover) { + final MarkupContent content = new MarkupContent(); + content.setKind(MarkupKind.MARKDOWN); + content.setValue(hover.markdown()); + + final Hover result = new Hover(); + result.setContents(content); + return result; + } + + @Override + public MessageParams mapInfoMessage(final String message) { + return new MessageParams(MessageType.Info, message); + } + + private Diagnostic mapDiagnostic(final BaselineDocumentIssue issue) { + final Diagnostic diagnostic = new Diagnostic(); + diagnostic.setRange(new Range( + new Position(issue.startLine(), issue.startCharacter()), + new Position(issue.endLine(), issue.endCharacter()))); + diagnostic.setSeverity(mapSeverity(issue.severity())); + diagnostic.setSource(issue.source()); + diagnostic.setMessage(issue.message()); + return diagnostic; + } + + private DiagnosticSeverity mapSeverity(final BaselineIssueSeverity severity) { + return switch (severity) { + case INFORMATION -> DiagnosticSeverity.Information; + case WARNING -> DiagnosticSeverity.Warning; + case ERROR -> DiagnosticSeverity.Error; + }; + } +} diff --git a/prometeu-lsp/prometeu-lsp-v1/src/main/java/p/studio/lsp/v1/protocol/mapping/ProtocolMessageMapper.java b/prometeu-lsp/prometeu-lsp-v1/src/main/java/p/studio/lsp/v1/protocol/mapping/ProtocolMessageMapper.java new file mode 100644 index 00000000..d1f9922d --- /dev/null +++ b/prometeu-lsp/prometeu-lsp-v1/src/main/java/p/studio/lsp/v1/protocol/mapping/ProtocolMessageMapper.java @@ -0,0 +1,21 @@ +package p.studio.lsp.v1.protocol.mapping; + +import org.eclipse.lsp4j.Hover; +import org.eclipse.lsp4j.InitializeResult; +import org.eclipse.lsp4j.MessageParams; +import org.eclipse.lsp4j.PublishDiagnosticsParams; +import p.studio.lsp.v1.compiler.BaselineDocumentAnalysis; +import p.studio.lsp.v1.compiler.BaselineHover; +import p.studio.lsp.v1.compiler.BaselineServerDescription; + +public interface ProtocolMessageMapper { + InitializeResult mapInitializeResult(BaselineServerDescription description); + + PublishDiagnosticsParams mapDiagnostics(String uri, BaselineDocumentAnalysis analysis); + + PublishDiagnosticsParams emptyDiagnostics(String uri); + + Hover mapHover(BaselineHover hover); + + MessageParams mapInfoMessage(String message); +} diff --git a/prometeu-lsp/prometeu-lsp-v1/src/main/java/p/studio/lsp/v1/protocol/mapping/ProtocolServerProfile.java b/prometeu-lsp/prometeu-lsp-v1/src/main/java/p/studio/lsp/v1/protocol/mapping/ProtocolServerProfile.java deleted file mode 100644 index 75b4bc8a..00000000 --- a/prometeu-lsp/prometeu-lsp-v1/src/main/java/p/studio/lsp/v1/protocol/mapping/ProtocolServerProfile.java +++ /dev/null @@ -1,11 +0,0 @@ -package p.studio.lsp.v1.protocol.mapping; - -public record ProtocolServerProfile( - String name, - String version, - boolean hoverSupported) { - - public static ProtocolServerProfile defaults() { - return new ProtocolServerProfile("Prometeu Studio LSP", "0.1.0", true); - } -} diff --git a/prometeu-lsp/prometeu-lsp-v1/src/main/java/p/studio/lsp/v1/protocol/mapping/ServerCapabilitiesMapper.java b/prometeu-lsp/prometeu-lsp-v1/src/main/java/p/studio/lsp/v1/protocol/mapping/ServerCapabilitiesMapper.java deleted file mode 100644 index 5f5c4a0c..00000000 --- a/prometeu-lsp/prometeu-lsp-v1/src/main/java/p/studio/lsp/v1/protocol/mapping/ServerCapabilitiesMapper.java +++ /dev/null @@ -1,27 +0,0 @@ -package p.studio.lsp.v1.protocol.mapping; - -import org.eclipse.lsp4j.*; - -public final class ServerCapabilitiesMapper { - public InitializeResult map(final ProtocolServerProfile profile) { - final ServerCapabilities capabilities = new ServerCapabilities(); - - final TextDocumentSyncOptions syncOptions = new TextDocumentSyncOptions(); - syncOptions.setOpenClose(true); - syncOptions.setChange(TextDocumentSyncKind.Full); - - final SaveOptions saveOptions = new SaveOptions(); - saveOptions.setIncludeText(true); - syncOptions.setSave(saveOptions); - - capabilities.setTextDocumentSync(syncOptions); - capabilities.setHoverProvider(profile.hoverSupported()); - - final InitializeResult result = new InitializeResult(capabilities); - final ServerInfo serverInfo = new ServerInfo(); - serverInfo.setName(profile.name()); - serverInfo.setVersion(profile.version()); - result.setServerInfo(serverInfo); - return result; - } -} diff --git a/prometeu-lsp/prometeu-lsp-v1/src/test/java/p/studio/lsp/v1/compiler/CompilerLanguageServiceBridgeTest.java b/prometeu-lsp/prometeu-lsp-v1/src/test/java/p/studio/lsp/v1/compiler/CompilerLanguageServiceBridgeTest.java new file mode 100644 index 00000000..1db5da43 --- /dev/null +++ b/prometeu-lsp/prometeu-lsp-v1/src/test/java/p/studio/lsp/v1/compiler/CompilerLanguageServiceBridgeTest.java @@ -0,0 +1,29 @@ +package p.studio.lsp.v1.compiler; + +import org.junit.jupiter.api.Test; +import p.studio.lsp.api.LspProjectContext; + +import java.nio.file.Path; + +import static org.junit.jupiter.api.Assertions.assertEquals; +import static org.junit.jupiter.api.Assertions.assertFalse; +import static org.junit.jupiter.api.Assertions.assertTrue; + +class CompilerLanguageServiceBridgeTest { + + @Test + void bridgeProvidesStableBaselineResponses() { + final CompilerLanguageServiceBridge bridge = new CompilerLanguageServiceBridge(); + final LspProjectContext project = new LspProjectContext("demo", "pbs", Path.of(".")); + + final BaselineServerDescription server = bridge.describeServer(project); + final BaselineDocumentAnalysis analysis = bridge.analyzeDocument(project, "file:///demo.pbs", "let x = 1"); + final BaselineHover hover = bridge.hover(project, "file:///demo.pbs", 0, 0); + + assertEquals("Prometeu Studio LSP", server.name()); + assertTrue(server.hoverSupported()); + assertFalse(analysis.issues().isEmpty()); + assertTrue(analysis.issues().getFirst().message().contains("BuilderPipelineService")); + assertTrue(hover.markdown().contains("Compiler-backed baseline")); + } +} diff --git a/prometeu-lsp/prometeu-lsp-v1/src/test/java/p/studio/lsp/v1/protocol/PrometeuLanguageServerTest.java b/prometeu-lsp/prometeu-lsp-v1/src/test/java/p/studio/lsp/v1/protocol/PrometeuLanguageServerTest.java new file mode 100644 index 00000000..819d4c5e --- /dev/null +++ b/prometeu-lsp/prometeu-lsp-v1/src/test/java/p/studio/lsp/v1/protocol/PrometeuLanguageServerTest.java @@ -0,0 +1,116 @@ +package p.studio.lsp.v1.protocol; + +import org.eclipse.lsp4j.InitializeParams; +import org.eclipse.lsp4j.InitializeResult; +import org.eclipse.lsp4j.PublishDiagnosticsParams; +import org.eclipse.lsp4j.services.TextDocumentService; +import org.eclipse.lsp4j.services.WorkspaceService; +import org.junit.jupiter.api.Test; +import p.studio.lsp.api.LspProjectContext; +import p.studio.lsp.v1.compiler.*; +import p.studio.lsp.v1.protocol.mapping.ProtocolMessageMapper; + +import java.nio.file.Path; +import java.util.List; + +import static org.junit.jupiter.api.Assertions.assertEquals; +import static org.junit.jupiter.api.Assertions.assertSame; + +class PrometeuLanguageServerTest { + + @Test + void initializeDelegatesThroughBridgeAndMapper() { + final RecordingBridge bridge = new RecordingBridge(); + final RecordingMapper mapper = new RecordingMapper(); + final InitializeResult expected = new InitializeResult(); + mapper.initializeResult = expected; + + final PrometeuLanguageServer server = new PrometeuLanguageServer( + new LspProjectContext("demo", "pbs", Path.of(".")), + bridge, + mapper, + new NoopTextDocumentService(), + new PrometeuWorkspaceService()); + + final InitializeResult result = server.initialize(new InitializeParams()).join(); + + assertSame(expected, result); + assertEquals(1, bridge.describeServerCalls); + assertSame(bridge.serverDescription, mapper.lastServerDescription); + } + + private static final class RecordingBridge implements LanguageServiceBridge { + private int describeServerCalls; + private final BaselineServerDescription serverDescription = new BaselineServerDescription("demo", "1", true); + + @Override + public BaselineServerDescription describeServer(final LspProjectContext project) { + describeServerCalls++; + return serverDescription; + } + + @Override + public BaselineDocumentAnalysis analyzeDocument(final LspProjectContext project, final String documentUri, final String text) { + return new BaselineDocumentAnalysis(List.of()); + } + + @Override + public BaselineHover hover(final LspProjectContext project, final String documentUri, final int line, final int character) { + return new BaselineHover("hover"); + } + + @Override + public String onSave(final LspProjectContext project, final String documentUri) { + return "saved"; + } + } + + private static final class RecordingMapper implements ProtocolMessageMapper { + private InitializeResult initializeResult; + private BaselineServerDescription lastServerDescription; + + @Override + public InitializeResult mapInitializeResult(final BaselineServerDescription description) { + lastServerDescription = description; + return initializeResult; + } + + @Override + public PublishDiagnosticsParams mapDiagnostics(final String uri, final BaselineDocumentAnalysis analysis) { + throw new UnsupportedOperationException(); + } + + @Override + public PublishDiagnosticsParams emptyDiagnostics(final String uri) { + throw new UnsupportedOperationException(); + } + + @Override + public org.eclipse.lsp4j.Hover mapHover(final BaselineHover hover) { + throw new UnsupportedOperationException(); + } + + @Override + public org.eclipse.lsp4j.MessageParams mapInfoMessage(final String message) { + return new org.eclipse.lsp4j.MessageParams(); + } + } + + private static final class NoopTextDocumentService implements TextDocumentService { + @Override + public void didOpen(final org.eclipse.lsp4j.DidOpenTextDocumentParams params) { + } + + @Override + public void didChange(final org.eclipse.lsp4j.DidChangeTextDocumentParams params) { + } + + @Override + public void didClose(final org.eclipse.lsp4j.DidCloseTextDocumentParams params) { + } + + @Override + public void didSave(final org.eclipse.lsp4j.DidSaveTextDocumentParams params) { + } + } +} diff --git a/prometeu-lsp/prometeu-lsp-v1/src/test/java/p/studio/lsp/v1/protocol/PrometeuTextDocumentServiceTest.java b/prometeu-lsp/prometeu-lsp-v1/src/test/java/p/studio/lsp/v1/protocol/PrometeuTextDocumentServiceTest.java new file mode 100644 index 00000000..f7b442d2 --- /dev/null +++ b/prometeu-lsp/prometeu-lsp-v1/src/test/java/p/studio/lsp/v1/protocol/PrometeuTextDocumentServiceTest.java @@ -0,0 +1,136 @@ +package p.studio.lsp.v1.protocol; + +import org.eclipse.lsp4j.*; +import org.eclipse.lsp4j.services.LanguageClient; +import org.junit.jupiter.api.Test; +import p.studio.lsp.api.LspProjectContext; +import p.studio.lsp.v1.compiler.*; +import p.studio.lsp.v1.protocol.mapping.ProtocolMessageMapper; + +import java.nio.file.Path; +import java.util.List; +import java.util.concurrent.CompletableFuture; + +import static org.junit.jupiter.api.Assertions.assertEquals; +import static org.junit.jupiter.api.Assertions.assertSame; + +class PrometeuTextDocumentServiceTest { + + @Test + void documentEventsDelegateToBridgeAndMapper() { + final RecordingBridge bridge = new RecordingBridge(); + final RecordingMapper mapper = new RecordingMapper(); + final RecordingClient client = new RecordingClient(); + final PrometeuTextDocumentService service = new PrometeuTextDocumentService( + new LspProjectContext("demo", "pbs", Path.of(".")), + bridge, + mapper); + service.connect(client); + + service.didOpen(new DidOpenTextDocumentParams(new TextDocumentItem("file:///demo.pbs", "pbs", 1, "abc"))); + service.didSave(new DidSaveTextDocumentParams(new TextDocumentIdentifier("file:///demo.pbs"), "abc")); + service.hover(new HoverParams(new TextDocumentIdentifier("file:///demo.pbs"), new Position(0, 0))).join(); + + assertEquals(1, bridge.analyzeCalls); + assertEquals(1, bridge.saveCalls); + assertEquals(1, bridge.hoverCalls); + assertSame(bridge.lastAnalysis, mapper.lastAnalysis); + assertSame(bridge.lastHover, mapper.lastHover); + assertSame(mapper.diagnostics, client.lastDiagnostics); + assertSame(mapper.infoMessage, client.lastLogMessage); + } + + private static final class RecordingBridge implements LanguageServiceBridge { + private int analyzeCalls; + private int saveCalls; + private int hoverCalls; + private final BaselineDocumentAnalysis lastAnalysis = new BaselineDocumentAnalysis(List.of( + new BaselineDocumentIssue(0, 0, 0, 1, BaselineIssueSeverity.INFORMATION, "src", "msg"))); + private final BaselineHover lastHover = new BaselineHover("hover"); + + @Override + public BaselineServerDescription describeServer(final LspProjectContext project) { + return new BaselineServerDescription("demo", "1", true); + } + + @Override + public BaselineDocumentAnalysis analyzeDocument(final LspProjectContext project, final String documentUri, final String text) { + analyzeCalls++; + return lastAnalysis; + } + + @Override + public BaselineHover hover(final LspProjectContext project, final String documentUri, final int line, final int character) { + hoverCalls++; + return lastHover; + } + + @Override + public String onSave(final LspProjectContext project, final String documentUri) { + saveCalls++; + return "saved"; + } + } + + private static final class RecordingMapper implements ProtocolMessageMapper { + private final PublishDiagnosticsParams diagnostics = new PublishDiagnosticsParams("file:///demo.pbs", List.of()); + private final MessageParams infoMessage = new MessageParams(MessageType.Info, "saved"); + private BaselineDocumentAnalysis lastAnalysis; + private BaselineHover lastHover; + + @Override + public InitializeResult mapInitializeResult(final BaselineServerDescription description) { + throw new UnsupportedOperationException(); + } + + @Override + public PublishDiagnosticsParams mapDiagnostics(final String uri, final BaselineDocumentAnalysis analysis) { + lastAnalysis = analysis; + return diagnostics; + } + + @Override + public PublishDiagnosticsParams emptyDiagnostics(final String uri) { + return new PublishDiagnosticsParams(uri, List.of()); + } + + @Override + public Hover mapHover(final BaselineHover hover) { + lastHover = hover; + return new Hover(); + } + + @Override + public MessageParams mapInfoMessage(final String message) { + return infoMessage; + } + } + + private static final class RecordingClient implements LanguageClient { + private PublishDiagnosticsParams lastDiagnostics; + private MessageParams lastLogMessage; + + @Override + public void telemetryEvent(final Object object) { + } + + @Override + public void publishDiagnostics(final PublishDiagnosticsParams diagnostics) { + lastDiagnostics = diagnostics; + } + + @Override + public void showMessage(final MessageParams messageParams) { + } + + @Override + public CompletableFuture showMessageRequest(final ShowMessageRequestParams requestParams) { + return CompletableFuture.completedFuture(null); + } + + @Override + public void logMessage(final MessageParams message) { + lastLogMessage = message; + } + } +} -- 2.47.2 From ba88dee8cb89bfb40cc4d5acd290105cef9bf86a Mon Sep 17 00:00:00 2001 From: bQUARKz Date: Tue, 5 May 2026 16:23:57 +0100 Subject: [PATCH 09/37] connection checker and failure --- .../studio/lsp/v1/PrometeuStudioLspMain.java | 29 - .../protocol/ProjectConnectionValidator.java | 79 ++ .../v1/protocol/PrometeuLanguageServer.java | 7 + .../mapping/Lsp4jProtocolMessageMapper.java | 6 + .../mapping/ProtocolMessageMapper.java | 1 + .../protocol/PrometeuLanguageServerTest.java | 59 +- .../PrometeuTextDocumentServiceTest.java | 5 + .../main/assets/.prometeu/cache.json | 784 +++++++++--------- 8 files changed, 548 insertions(+), 422 deletions(-) delete mode 100644 prometeu-lsp/prometeu-lsp-v1/src/main/java/p/studio/lsp/v1/PrometeuStudioLspMain.java create mode 100644 prometeu-lsp/prometeu-lsp-v1/src/main/java/p/studio/lsp/v1/protocol/ProjectConnectionValidator.java diff --git a/prometeu-lsp/prometeu-lsp-v1/src/main/java/p/studio/lsp/v1/PrometeuStudioLspMain.java b/prometeu-lsp/prometeu-lsp-v1/src/main/java/p/studio/lsp/v1/PrometeuStudioLspMain.java deleted file mode 100644 index 8cb8a407..00000000 --- a/prometeu-lsp/prometeu-lsp-v1/src/main/java/p/studio/lsp/v1/PrometeuStudioLspMain.java +++ /dev/null @@ -1,29 +0,0 @@ -package p.studio.lsp.v1; - -import p.studio.lsp.api.LspProjectContext; -import p.studio.lsp.api.LspServerBootRequest; -import p.studio.lsp.v1.bootstrap.LspV1ServerLifecycle; -import p.studio.lsp.v1.compiler.CompilerLanguageServiceBridge; -import p.studio.lsp.v1.host.TcpLspServerHostFactory; - -import java.nio.file.Path; - -public final class PrometeuStudioLspMain { - private PrometeuStudioLspMain() { - } - - public static void main(final String[] args) throws Exception { - final var lifecycle = new LspV1ServerLifecycle( - new TcpLspServerHostFactory(), - new CompilerLanguageServiceBridge()); - - final var request = LspServerBootRequest.defaults(new LspProjectContext( - "standalone-mock", - "pbs", - Path.of("."))); - - final var handle = lifecycle.bootServer(request); - System.out.println("Prometeu Studio LSP listening on " + handle.endpoint().host() + ":" + handle.endpoint().port()); - Thread.currentThread().join(); - } -} diff --git a/prometeu-lsp/prometeu-lsp-v1/src/main/java/p/studio/lsp/v1/protocol/ProjectConnectionValidator.java b/prometeu-lsp/prometeu-lsp-v1/src/main/java/p/studio/lsp/v1/protocol/ProjectConnectionValidator.java new file mode 100644 index 00000000..2dbf3a64 --- /dev/null +++ b/prometeu-lsp/prometeu-lsp-v1/src/main/java/p/studio/lsp/v1/protocol/ProjectConnectionValidator.java @@ -0,0 +1,79 @@ +package p.studio.lsp.v1.protocol; + +import org.eclipse.lsp4j.InitializeParams; +import org.eclipse.lsp4j.WorkspaceFolder; +import org.eclipse.lsp4j.jsonrpc.ResponseErrorException; +import org.eclipse.lsp4j.jsonrpc.messages.ResponseError; +import org.eclipse.lsp4j.jsonrpc.messages.ResponseErrorCode; +import p.studio.lsp.api.LspProjectContext; + +import java.net.URI; +import java.nio.file.Path; +import java.util.ArrayList; +import java.util.List; +import java.util.Objects; + +final class ProjectConnectionValidator { + private ProjectConnectionValidator() { + } + + static void validateProjectBinding( + final LspProjectContext project, + final InitializeParams params) { + final LspProjectContext safeProject = Objects.requireNonNull(project, "project"); + final InitializeParams safeParams = Objects.requireNonNull(params, "params"); + + final Path expectedRoot = safeProject.projectRoot().toAbsolutePath().normalize(); + final List clientRoots = extractClientRoots(safeParams); + if (clientRoots.isEmpty()) { + throw mismatch(safeProject, "client did not declare rootUri or workspaceFolders"); + } + + for (final Path clientRoot : clientRoots) { + if (expectedRoot.equals(clientRoot)) { + return; + } + } + + throw mismatch(safeProject, "client roots " + clientRoots + " do not match " + expectedRoot); + } + + private static List extractClientRoots(final InitializeParams params) { + final List roots = new ArrayList<>(); + if (params.getRootUri() != null && !params.getRootUri().isBlank()) { + roots.add(parsePath(params.getRootUri())); + } + if (params.getWorkspaceFolders() != null) { + for (final WorkspaceFolder workspaceFolder : params.getWorkspaceFolders()) { + if (workspaceFolder == null || workspaceFolder.getUri() == null || workspaceFolder.getUri().isBlank()) { + continue; + } + roots.add(parsePath(workspaceFolder.getUri())); + } + } + return List.copyOf(roots); + } + + private static Path parsePath(final String rawUri) { + try { + return Path.of(URI.create(rawUri)).toAbsolutePath().normalize(); + } catch (RuntimeException exception) { + throw new ResponseErrorException(new ResponseError( + ResponseErrorCode.InvalidParams, + "invalid project root uri from client: " + rawUri, + null)); + } + } + + private static ResponseErrorException mismatch( + final LspProjectContext project, + final String detail) { + return new ResponseErrorException(new ResponseError( + ResponseErrorCode.InvalidParams, + "Prometeu Studio LSP is bound to project root " + + project.projectRoot() + + " and rejected this client: " + + detail, + null)); + } +} diff --git a/prometeu-lsp/prometeu-lsp-v1/src/main/java/p/studio/lsp/v1/protocol/PrometeuLanguageServer.java b/prometeu-lsp/prometeu-lsp-v1/src/main/java/p/studio/lsp/v1/protocol/PrometeuLanguageServer.java index 3cf5b036..2a467e08 100644 --- a/prometeu-lsp/prometeu-lsp-v1/src/main/java/p/studio/lsp/v1/protocol/PrometeuLanguageServer.java +++ b/prometeu-lsp/prometeu-lsp-v1/src/main/java/p/studio/lsp/v1/protocol/PrometeuLanguageServer.java @@ -59,6 +59,13 @@ public final class PrometeuLanguageServer implements LanguageServer, LanguageCli @Override public CompletableFuture initialize(final InitializeParams params) { + try { + ProjectConnectionValidator.validateProjectBinding(project, params); + } catch (RuntimeException runtimeException) { + client.logMessage(protocolMessageMapper.mapInfoMessage( + "Failed to initialize Prometeu Studio LSP for project " + project.projectKey() + ": " + runtimeException.getMessage())); + return CompletableFuture.failedFuture(runtimeException); + } return CompletableFuture.completedFuture(protocolMessageMapper.mapInitializeResult( languageServiceBridge.describeServer(project))); } diff --git a/prometeu-lsp/prometeu-lsp-v1/src/main/java/p/studio/lsp/v1/protocol/mapping/Lsp4jProtocolMessageMapper.java b/prometeu-lsp/prometeu-lsp-v1/src/main/java/p/studio/lsp/v1/protocol/mapping/Lsp4jProtocolMessageMapper.java index a6cee146..8b9cf2bd 100644 --- a/prometeu-lsp/prometeu-lsp-v1/src/main/java/p/studio/lsp/v1/protocol/mapping/Lsp4jProtocolMessageMapper.java +++ b/prometeu-lsp/prometeu-lsp-v1/src/main/java/p/studio/lsp/v1/protocol/mapping/Lsp4jProtocolMessageMapper.java @@ -57,6 +57,11 @@ public final class Lsp4jProtocolMessageMapper implements ProtocolMessageMapper { return new MessageParams(MessageType.Info, message); } + @Override + public MessageParams mapErrorMessage(final String message) { + return new MessageParams(MessageType.Error, message); + } + private Diagnostic mapDiagnostic(final BaselineDocumentIssue issue) { final Diagnostic diagnostic = new Diagnostic(); diagnostic.setRange(new Range( @@ -68,6 +73,7 @@ public final class Lsp4jProtocolMessageMapper implements ProtocolMessageMapper { return diagnostic; } + private DiagnosticSeverity mapSeverity(final BaselineIssueSeverity severity) { return switch (severity) { case INFORMATION -> DiagnosticSeverity.Information; diff --git a/prometeu-lsp/prometeu-lsp-v1/src/main/java/p/studio/lsp/v1/protocol/mapping/ProtocolMessageMapper.java b/prometeu-lsp/prometeu-lsp-v1/src/main/java/p/studio/lsp/v1/protocol/mapping/ProtocolMessageMapper.java index d1f9922d..83d09bd1 100644 --- a/prometeu-lsp/prometeu-lsp-v1/src/main/java/p/studio/lsp/v1/protocol/mapping/ProtocolMessageMapper.java +++ b/prometeu-lsp/prometeu-lsp-v1/src/main/java/p/studio/lsp/v1/protocol/mapping/ProtocolMessageMapper.java @@ -18,4 +18,5 @@ public interface ProtocolMessageMapper { Hover mapHover(BaselineHover hover); MessageParams mapInfoMessage(String message); + MessageParams mapErrorMessage(String message); } diff --git a/prometeu-lsp/prometeu-lsp-v1/src/test/java/p/studio/lsp/v1/protocol/PrometeuLanguageServerTest.java b/prometeu-lsp/prometeu-lsp-v1/src/test/java/p/studio/lsp/v1/protocol/PrometeuLanguageServerTest.java index 819d4c5e..9c64cdba 100644 --- a/prometeu-lsp/prometeu-lsp-v1/src/test/java/p/studio/lsp/v1/protocol/PrometeuLanguageServerTest.java +++ b/prometeu-lsp/prometeu-lsp-v1/src/test/java/p/studio/lsp/v1/protocol/PrometeuLanguageServerTest.java @@ -2,6 +2,8 @@ package p.studio.lsp.v1.protocol; import org.eclipse.lsp4j.InitializeParams; import org.eclipse.lsp4j.InitializeResult; +import org.eclipse.lsp4j.WorkspaceFolder; +import org.eclipse.lsp4j.jsonrpc.ResponseErrorException; import org.eclipse.lsp4j.PublishDiagnosticsParams; import org.eclipse.lsp4j.services.TextDocumentService; import org.eclipse.lsp4j.services.WorkspaceService; @@ -12,9 +14,12 @@ import p.studio.lsp.v1.protocol.mapping.ProtocolMessageMapper; import java.nio.file.Path; import java.util.List; +import java.util.concurrent.CompletionException; import static org.junit.jupiter.api.Assertions.assertEquals; +import static org.junit.jupiter.api.Assertions.assertInstanceOf; import static org.junit.jupiter.api.Assertions.assertSame; +import static org.junit.jupiter.api.Assertions.assertTrue; class PrometeuLanguageServerTest { @@ -32,13 +37,60 @@ class PrometeuLanguageServerTest { new NoopTextDocumentService(), new PrometeuWorkspaceService()); - final InitializeResult result = server.initialize(new InitializeParams()).join(); + final InitializeParams params = new InitializeParams(); + params.setRootUri(Path.of(".").toAbsolutePath().normalize().toUri().toString()); + + final InitializeResult result = server.initialize(params).join(); assertSame(expected, result); assertEquals(1, bridge.describeServerCalls); assertSame(bridge.serverDescription, mapper.lastServerDescription); } + @Test + void initializeRejectsClientBoundToDifferentProjectRoot() { + final RecordingBridge bridge = new RecordingBridge(); + final RecordingMapper mapper = new RecordingMapper(); + final PrometeuLanguageServer server = new PrometeuLanguageServer( + new LspProjectContext("demo", "pbs", Path.of("/tmp/studio-project")), + bridge, + mapper, + new NoopTextDocumentService(), + new PrometeuWorkspaceService()); + + final InitializeParams params = new InitializeParams(); + params.setRootUri(Path.of("/tmp/another-project").toUri().toString()); + + final CompletionException failure = org.junit.jupiter.api.Assertions.assertThrows( + CompletionException.class, + () -> server.initialize(params).join()); + + final ResponseErrorException responseError = assertInstanceOf(ResponseErrorException.class, failure.getCause()); + assertTrue(responseError.getMessage().contains("/tmp/studio-project")); + assertEquals(0, bridge.describeServerCalls); + } + + @Test + void initializeAcceptsMatchingWorkspaceFolder() { + final RecordingBridge bridge = new RecordingBridge(); + final RecordingMapper mapper = new RecordingMapper(); + mapper.initializeResult = new InitializeResult(); + final Path projectRoot = Path.of("/tmp/studio-project").toAbsolutePath().normalize(); + final PrometeuLanguageServer server = new PrometeuLanguageServer( + new LspProjectContext("demo", "pbs", projectRoot), + bridge, + mapper, + new NoopTextDocumentService(), + new PrometeuWorkspaceService()); + + final InitializeParams params = new InitializeParams(); + params.setWorkspaceFolders(List.of(new WorkspaceFolder(projectRoot.toUri().toString(), "studio-project"))); + + server.initialize(params).join(); + + assertEquals(1, bridge.describeServerCalls); + } + private static final class RecordingBridge implements LanguageServiceBridge { private int describeServerCalls; private final BaselineServerDescription serverDescription = new BaselineServerDescription("demo", "1", true); @@ -94,6 +146,11 @@ class PrometeuLanguageServerTest { public org.eclipse.lsp4j.MessageParams mapInfoMessage(final String message) { return new org.eclipse.lsp4j.MessageParams(); } + + @Override + public org.eclipse.lsp4j.MessageParams mapErrorMessage(final String message) { + return new org.eclipse.lsp4j.MessageParams(); + } } private static final class NoopTextDocumentService implements TextDocumentService { diff --git a/prometeu-lsp/prometeu-lsp-v1/src/test/java/p/studio/lsp/v1/protocol/PrometeuTextDocumentServiceTest.java b/prometeu-lsp/prometeu-lsp-v1/src/test/java/p/studio/lsp/v1/protocol/PrometeuTextDocumentServiceTest.java index f7b442d2..a1e05504 100644 --- a/prometeu-lsp/prometeu-lsp-v1/src/test/java/p/studio/lsp/v1/protocol/PrometeuTextDocumentServiceTest.java +++ b/prometeu-lsp/prometeu-lsp-v1/src/test/java/p/studio/lsp/v1/protocol/PrometeuTextDocumentServiceTest.java @@ -104,6 +104,11 @@ class PrometeuTextDocumentServiceTest { public MessageParams mapInfoMessage(final String message) { return infoMessage; } + + @Override + public MessageParams mapErrorMessage(final String message) { + return infoMessage; + } } private static final class RecordingClient implements LanguageClient { diff --git a/test-projects/main/assets/.prometeu/cache.json b/test-projects/main/assets/.prometeu/cache.json index 7d30e3eb..0a8c0fad 100644 --- a/test-projects/main/assets/.prometeu/cache.json +++ b/test-projects/main/assets/.prometeu/cache.json @@ -24,14 +24,14 @@ "last_modified" : 1774359772403, "fingerprint" : "eeb7cc665386299403b7be1c272375d5077f3647c587f8033aa8c9275f840562", "metadata" : { - "palette" : { - "originalArgb8888" : [ -265674 ], - "convertedRgb565" : [ -122 ] - }, "tile" : { "width" : 32, "height" : 32, "paletteIndices" : "AQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAAAAAAAAAAABAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEAAAAAAAAAAAEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQAAAAAAAAAAAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAAAAAAAAAAABAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEAAAAAAAAAAAEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQAAAAAAAAAAAQEBAQEBAQEBAQEBAAAAAAAAAAAAAAAAAAAAAAAAAAABAQEBAQEBAQEBAQEAAAAAAAAAAAAAAAAAAAAAAAAAAAEBAQEBAQEBAQEBAQAAAAAAAAAAAAAAAAAAAAAAAAAAAQEBAQEBAQEBAQEBAAAAAAAAAAAAAAAAAAAAAAAAAAABAQEBAQEBAQEBAQEAAAAAAAAAAAAAAAAAAAAAAAAAAAEBAQEBAQEBAQEBAQAAAAAAAAAAAAAAAAAAAAAAAAAAAQEBAQEBAQEBAQEBAAAAAAAAAAAAAAAAAAAAAAAAAAABAQEBAQEBAQEBAQEAAAAAAAAAAAAAAAAAAAAAAAAAAAEBAQEBAQEBAQEBAQAAAAAAAAAAAAAAAAAAAQEBAQEBAQEBAQEBAQEBAQEBAAAAAAAAAAAAAAAAAAABAQEBAQEBAQEBAQEBAQEBAQEAAAAAAAAAAAAAAAAAAAEBAQEBAQEBAQEBAQEBAQEBAQAAAAAAAAAAAAAAAAAAAQEBAQEBAQEBAQEBAAAAAAAAAAAAAAAAAAAAAAAAAAABAQEBAQEBAQEBAQEAAAAAAAAAAAAAAAAAAAAAAAAAAAEBAQEBAQEBAQEBAQAAAAAAAAAAAAAAAAAAAQEBAQEBAQEBAQEBAQEBAQEBAAAAAAAAAAAAAAAAAAABAQEBAQEBAQEBAQEBAQEBAQEAAAAAAAAAAAAAAAAAAAEBAQEBAQEBAQEBAQEBAQEBAQAAAAAAAAAAAAAAAAAAAQEBAQEBAQEBAQEBAQEBAQEBAAAAAAAAAAAAAAAAAAABAQEBAQEBAQEBAQEBAQEBAQEAAAAAAAAAAAAAAAAAAAEBAQEBAQEBAQEBAQ==" + }, + "palette" : { + "originalArgb8888" : [ -265674 ], + "convertedRgb565" : [ -122 ] } }, "diagnostics" : [ ] @@ -42,14 +42,14 @@ "last_modified" : 1774359772405, "fingerprint" : "eeb7cc665386299403b7be1c272375d5077f3647c587f8033aa8c9275f840562", "metadata" : { - "palette" : { - "originalArgb8888" : [ -265674 ], - "convertedRgb565" : [ -122 ] - }, "tile" : { "width" : 32, "height" : 32, "paletteIndices" : "AQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAAAAAAAAAAABAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEAAAAAAAAAAAEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQAAAAAAAAAAAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAAAAAAAAAAABAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEAAAAAAAAAAAEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQAAAAAAAAAAAQEBAQEBAQEBAQEBAAAAAAAAAAAAAAAAAAAAAAAAAAABAQEBAQEBAQEBAQEAAAAAAAAAAAAAAAAAAAAAAAAAAAEBAQEBAQEBAQEBAQAAAAAAAAAAAAAAAAAAAAAAAAAAAQEBAQEBAQEBAQEBAAAAAAAAAAAAAAAAAAAAAAAAAAABAQEBAQEBAQEBAQEAAAAAAAAAAAAAAAAAAAAAAAAAAAEBAQEBAQEBAQEBAQAAAAAAAAAAAAAAAAAAAAAAAAAAAQEBAQEBAQEBAQEBAAAAAAAAAAAAAAAAAAAAAAAAAAABAQEBAQEBAQEBAQEAAAAAAAAAAAAAAAAAAAAAAAAAAAEBAQEBAQEBAQEBAQAAAAAAAAAAAAAAAAAAAQEBAQEBAQEBAQEBAQEBAQEBAAAAAAAAAAAAAAAAAAABAQEBAQEBAQEBAQEBAQEBAQEAAAAAAAAAAAAAAAAAAAEBAQEBAQEBAQEBAQEBAQEBAQAAAAAAAAAAAAAAAAAAAQEBAQEBAQEBAQEBAAAAAAAAAAAAAAAAAAAAAAAAAAABAQEBAQEBAQEBAQEAAAAAAAAAAAAAAAAAAAAAAAAAAAEBAQEBAQEBAQEBAQAAAAAAAAAAAAAAAAAAAQEBAQEBAQEBAQEBAQEBAQEBAAAAAAAAAAAAAAAAAAABAQEBAQEBAQEBAQEBAQEBAQEAAAAAAAAAAAAAAAAAAAEBAQEBAQEBAQEBAQEBAQEBAQAAAAAAAAAAAAAAAAAAAQEBAQEBAQEBAQEBAQEBAQEBAAAAAAAAAAAAAAAAAAABAQEBAQEBAQEBAQEBAQEBAQEAAAAAAAAAAAAAAAAAAAEBAQEBAQEBAQEBAQ==" + }, + "palette" : { + "originalArgb8888" : [ -265674 ], + "convertedRgb565" : [ -122 ] } }, "diagnostics" : [ ] @@ -60,14 +60,14 @@ "last_modified" : 1774359772406, "fingerprint" : "eeb7cc665386299403b7be1c272375d5077f3647c587f8033aa8c9275f840562", "metadata" : { - "palette" : { - "originalArgb8888" : [ -265674 ], - "convertedRgb565" : [ -122 ] - }, "tile" : { "width" : 32, "height" : 32, "paletteIndices" : "AQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAAAAAAAAAAABAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEAAAAAAAAAAAEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQAAAAAAAAAAAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAAAAAAAAAAABAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEAAAAAAAAAAAEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQAAAAAAAAAAAQEBAQEBAQEBAQEBAAAAAAAAAAAAAAAAAAAAAAAAAAABAQEBAQEBAQEBAQEAAAAAAAAAAAAAAAAAAAAAAAAAAAEBAQEBAQEBAQEBAQAAAAAAAAAAAAAAAAAAAAAAAAAAAQEBAQEBAQEBAQEBAAAAAAAAAAAAAAAAAAAAAAAAAAABAQEBAQEBAQEBAQEAAAAAAAAAAAAAAAAAAAAAAAAAAAEBAQEBAQEBAQEBAQAAAAAAAAAAAAAAAAAAAAAAAAAAAQEBAQEBAQEBAQEBAAAAAAAAAAAAAAAAAAAAAAAAAAABAQEBAQEBAQEBAQEAAAAAAAAAAAAAAAAAAAAAAAAAAAEBAQEBAQEBAQEBAQAAAAAAAAAAAAAAAAAAAQEBAQEBAQEBAQEBAQEBAQEBAAAAAAAAAAAAAAAAAAABAQEBAQEBAQEBAQEBAQEBAQEAAAAAAAAAAAAAAAAAAAEBAQEBAQEBAQEBAQEBAQEBAQAAAAAAAAAAAAAAAAAAAQEBAQEBAQEBAQEBAAAAAAAAAAAAAAAAAAAAAAAAAAABAQEBAQEBAQEBAQEAAAAAAAAAAAAAAAAAAAAAAAAAAAEBAQEBAQEBAQEBAQAAAAAAAAAAAAAAAAAAAQEBAQEBAQEBAQEBAQEBAQEBAAAAAAAAAAAAAAAAAAABAQEBAQEBAQEBAQEBAQEBAQEAAAAAAAAAAAAAAAAAAAEBAQEBAQEBAQEBAQEBAQEBAQAAAAAAAAAAAAAAAAAAAQEBAQEBAQEBAQEBAQEBAQEBAAAAAAAAAAAAAAAAAAABAQEBAQEBAQEBAQEBAQEBAQEAAAAAAAAAAAAAAAAAAAEBAQEBAQEBAQEBAQ==" + }, + "palette" : { + "originalArgb8888" : [ -265674 ], + "convertedRgb565" : [ -122 ] } }, "diagnostics" : [ ] @@ -78,14 +78,14 @@ "last_modified" : 1774359772408, "fingerprint" : "eeb7cc665386299403b7be1c272375d5077f3647c587f8033aa8c9275f840562", "metadata" : { - "palette" : { - "originalArgb8888" : [ -265674 ], - "convertedRgb565" : [ -122 ] - }, "tile" : { "width" : 32, "height" : 32, "paletteIndices" : "AQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAAAAAAAAAAABAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEAAAAAAAAAAAEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQAAAAAAAAAAAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAAAAAAAAAAABAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEAAAAAAAAAAAEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQAAAAAAAAAAAQEBAQEBAQEBAQEBAAAAAAAAAAAAAAAAAAAAAAAAAAABAQEBAQEBAQEBAQEAAAAAAAAAAAAAAAAAAAAAAAAAAAEBAQEBAQEBAQEBAQAAAAAAAAAAAAAAAAAAAAAAAAAAAQEBAQEBAQEBAQEBAAAAAAAAAAAAAAAAAAAAAAAAAAABAQEBAQEBAQEBAQEAAAAAAAAAAAAAAAAAAAAAAAAAAAEBAQEBAQEBAQEBAQAAAAAAAAAAAAAAAAAAAAAAAAAAAQEBAQEBAQEBAQEBAAAAAAAAAAAAAAAAAAAAAAAAAAABAQEBAQEBAQEBAQEAAAAAAAAAAAAAAAAAAAAAAAAAAAEBAQEBAQEBAQEBAQAAAAAAAAAAAAAAAAAAAQEBAQEBAQEBAQEBAQEBAQEBAAAAAAAAAAAAAAAAAAABAQEBAQEBAQEBAQEBAQEBAQEAAAAAAAAAAAAAAAAAAAEBAQEBAQEBAQEBAQEBAQEBAQAAAAAAAAAAAAAAAAAAAQEBAQEBAQEBAQEBAAAAAAAAAAAAAAAAAAAAAAAAAAABAQEBAQEBAQEBAQEAAAAAAAAAAAAAAAAAAAAAAAAAAAEBAQEBAQEBAQEBAQAAAAAAAAAAAAAAAAAAAQEBAQEBAQEBAQEBAQEBAQEBAAAAAAAAAAAAAAAAAAABAQEBAQEBAQEBAQEBAQEBAQEAAAAAAAAAAAAAAAAAAAEBAQEBAQEBAQEBAQEBAQEBAQAAAAAAAAAAAAAAAAAAAQEBAQEBAQEBAQEBAQEBAQEBAAAAAAAAAAAAAAAAAAABAQEBAQEBAQEBAQEBAQEBAQEAAAAAAAAAAAAAAAAAAAEBAQEBAQEBAQEBAQ==" + }, + "palette" : { + "originalArgb8888" : [ -265674 ], + "convertedRgb565" : [ -122 ] } }, "diagnostics" : [ ] @@ -96,14 +96,14 @@ "last_modified" : 1774359772409, "fingerprint" : "eeb7cc665386299403b7be1c272375d5077f3647c587f8033aa8c9275f840562", "metadata" : { - "palette" : { - "originalArgb8888" : [ -265674 ], - "convertedRgb565" : [ -122 ] - }, "tile" : { "width" : 32, "height" : 32, "paletteIndices" : "AQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAAAAAAAAAAABAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEAAAAAAAAAAAEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQAAAAAAAAAAAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAAAAAAAAAAABAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEAAAAAAAAAAAEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQAAAAAAAAAAAQEBAQEBAQEBAQEBAAAAAAAAAAAAAAAAAAAAAAAAAAABAQEBAQEBAQEBAQEAAAAAAAAAAAAAAAAAAAAAAAAAAAEBAQEBAQEBAQEBAQAAAAAAAAAAAAAAAAAAAAAAAAAAAQEBAQEBAQEBAQEBAAAAAAAAAAAAAAAAAAAAAAAAAAABAQEBAQEBAQEBAQEAAAAAAAAAAAAAAAAAAAAAAAAAAAEBAQEBAQEBAQEBAQAAAAAAAAAAAAAAAAAAAAAAAAAAAQEBAQEBAQEBAQEBAAAAAAAAAAAAAAAAAAAAAAAAAAABAQEBAQEBAQEBAQEAAAAAAAAAAAAAAAAAAAAAAAAAAAEBAQEBAQEBAQEBAQAAAAAAAAAAAAAAAAAAAQEBAQEBAQEBAQEBAQEBAQEBAAAAAAAAAAAAAAAAAAABAQEBAQEBAQEBAQEBAQEBAQEAAAAAAAAAAAAAAAAAAAEBAQEBAQEBAQEBAQEBAQEBAQAAAAAAAAAAAAAAAAAAAQEBAQEBAQEBAQEBAAAAAAAAAAAAAAAAAAAAAAAAAAABAQEBAQEBAQEBAQEAAAAAAAAAAAAAAAAAAAAAAAAAAAEBAQEBAQEBAQEBAQAAAAAAAAAAAAAAAAAAAQEBAQEBAQEBAQEBAQEBAQEBAAAAAAAAAAAAAAAAAAABAQEBAQEBAQEBAQEBAQEBAQEAAAAAAAAAAAAAAAAAAAEBAQEBAQEBAQEBAQEBAQEBAQAAAAAAAAAAAAAAAAAAAQEBAQEBAQEBAQEBAQEBAQEBAAAAAAAAAAAAAAAAAAABAQEBAQEBAQEBAQEBAQEBAQEAAAAAAAAAAAAAAAAAAAEBAQEBAQEBAQEBAQ==" + }, + "palette" : { + "originalArgb8888" : [ -265674 ], + "convertedRgb565" : [ -122 ] } }, "diagnostics" : [ ] @@ -114,14 +114,14 @@ "last_modified" : 1774359772411, "fingerprint" : "eeb7cc665386299403b7be1c272375d5077f3647c587f8033aa8c9275f840562", "metadata" : { - "palette" : { - "originalArgb8888" : [ -265674 ], - "convertedRgb565" : [ -122 ] - }, "tile" : { "width" : 32, "height" : 32, "paletteIndices" : "AQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAAAAAAAAAAABAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEAAAAAAAAAAAEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQAAAAAAAAAAAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAAAAAAAAAAABAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEAAAAAAAAAAAEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQAAAAAAAAAAAQEBAQEBAQEBAQEBAAAAAAAAAAAAAAAAAAAAAAAAAAABAQEBAQEBAQEBAQEAAAAAAAAAAAAAAAAAAAAAAAAAAAEBAQEBAQEBAQEBAQAAAAAAAAAAAAAAAAAAAAAAAAAAAQEBAQEBAQEBAQEBAAAAAAAAAAAAAAAAAAAAAAAAAAABAQEBAQEBAQEBAQEAAAAAAAAAAAAAAAAAAAAAAAAAAAEBAQEBAQEBAQEBAQAAAAAAAAAAAAAAAAAAAAAAAAAAAQEBAQEBAQEBAQEBAAAAAAAAAAAAAAAAAAAAAAAAAAABAQEBAQEBAQEBAQEAAAAAAAAAAAAAAAAAAAAAAAAAAAEBAQEBAQEBAQEBAQAAAAAAAAAAAAAAAAAAAQEBAQEBAQEBAQEBAQEBAQEBAAAAAAAAAAAAAAAAAAABAQEBAQEBAQEBAQEBAQEBAQEAAAAAAAAAAAAAAAAAAAEBAQEBAQEBAQEBAQEBAQEBAQAAAAAAAAAAAAAAAAAAAQEBAQEBAQEBAQEBAAAAAAAAAAAAAAAAAAAAAAAAAAABAQEBAQEBAQEBAQEAAAAAAAAAAAAAAAAAAAAAAAAAAAEBAQEBAQEBAQEBAQAAAAAAAAAAAAAAAAAAAQEBAQEBAQEBAQEBAQEBAQEBAAAAAAAAAAAAAAAAAAABAQEBAQEBAQEBAQEBAQEBAQEAAAAAAAAAAAAAAAAAAAEBAQEBAQEBAQEBAQEBAQEBAQAAAAAAAAAAAAAAAAAAAQEBAQEBAQEBAQEBAQEBAQEBAAAAAAAAAAAAAAAAAAABAQEBAQEBAQEBAQEBAQEBAQEAAAAAAAAAAAAAAAAAAAEBAQEBAQEBAQEBAQ==" + }, + "palette" : { + "originalArgb8888" : [ -265674 ], + "convertedRgb565" : [ -122 ] } }, "diagnostics" : [ ] @@ -132,14 +132,14 @@ "last_modified" : 1774359772412, "fingerprint" : "eeb7cc665386299403b7be1c272375d5077f3647c587f8033aa8c9275f840562", "metadata" : { - "palette" : { - "originalArgb8888" : [ -265674 ], - "convertedRgb565" : [ -122 ] - }, "tile" : { "width" : 32, "height" : 32, "paletteIndices" : "AQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAAAAAAAAAAABAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEAAAAAAAAAAAEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQAAAAAAAAAAAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAAAAAAAAAAABAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEAAAAAAAAAAAEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQAAAAAAAAAAAQEBAQEBAQEBAQEBAAAAAAAAAAAAAAAAAAAAAAAAAAABAQEBAQEBAQEBAQEAAAAAAAAAAAAAAAAAAAAAAAAAAAEBAQEBAQEBAQEBAQAAAAAAAAAAAAAAAAAAAAAAAAAAAQEBAQEBAQEBAQEBAAAAAAAAAAAAAAAAAAAAAAAAAAABAQEBAQEBAQEBAQEAAAAAAAAAAAAAAAAAAAAAAAAAAAEBAQEBAQEBAQEBAQAAAAAAAAAAAAAAAAAAAAAAAAAAAQEBAQEBAQEBAQEBAAAAAAAAAAAAAAAAAAAAAAAAAAABAQEBAQEBAQEBAQEAAAAAAAAAAAAAAAAAAAAAAAAAAAEBAQEBAQEBAQEBAQAAAAAAAAAAAAAAAAAAAQEBAQEBAQEBAQEBAQEBAQEBAAAAAAAAAAAAAAAAAAABAQEBAQEBAQEBAQEBAQEBAQEAAAAAAAAAAAAAAAAAAAEBAQEBAQEBAQEBAQEBAQEBAQAAAAAAAAAAAAAAAAAAAQEBAQEBAQEBAQEBAAAAAAAAAAAAAAAAAAAAAAAAAAABAQEBAQEBAQEBAQEAAAAAAAAAAAAAAAAAAAAAAAAAAAEBAQEBAQEBAQEBAQAAAAAAAAAAAAAAAAAAAQEBAQEBAQEBAQEBAQEBAQEBAAAAAAAAAAAAAAAAAAABAQEBAQEBAQEBAQEBAQEBAQEAAAAAAAAAAAAAAAAAAAEBAQEBAQEBAQEBAQEBAQEBAQAAAAAAAAAAAAAAAAAAAQEBAQEBAQEBAQEBAQEBAQEBAAAAAAAAAAAAAAAAAAABAQEBAQEBAQEBAQEBAQEBAQEAAAAAAAAAAAAAAAAAAAEBAQEBAQEBAQEBAQ==" + }, + "palette" : { + "originalArgb8888" : [ -265674 ], + "convertedRgb565" : [ -122 ] } }, "diagnostics" : [ ] @@ -150,14 +150,14 @@ "last_modified" : 1774359772413, "fingerprint" : "eeb7cc665386299403b7be1c272375d5077f3647c587f8033aa8c9275f840562", "metadata" : { - "palette" : { - "originalArgb8888" : [ -265674 ], - "convertedRgb565" : [ -122 ] - }, "tile" : { "width" : 32, "height" : 32, "paletteIndices" : "AQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAAAAAAAAAAABAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEAAAAAAAAAAAEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQAAAAAAAAAAAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAAAAAAAAAAABAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEAAAAAAAAAAAEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQAAAAAAAAAAAQEBAQEBAQEBAQEBAAAAAAAAAAAAAAAAAAAAAAAAAAABAQEBAQEBAQEBAQEAAAAAAAAAAAAAAAAAAAAAAAAAAAEBAQEBAQEBAQEBAQAAAAAAAAAAAAAAAAAAAAAAAAAAAQEBAQEBAQEBAQEBAAAAAAAAAAAAAAAAAAAAAAAAAAABAQEBAQEBAQEBAQEAAAAAAAAAAAAAAAAAAAAAAAAAAAEBAQEBAQEBAQEBAQAAAAAAAAAAAAAAAAAAAAAAAAAAAQEBAQEBAQEBAQEBAAAAAAAAAAAAAAAAAAAAAAAAAAABAQEBAQEBAQEBAQEAAAAAAAAAAAAAAAAAAAAAAAAAAAEBAQEBAQEBAQEBAQAAAAAAAAAAAAAAAAAAAQEBAQEBAQEBAQEBAQEBAQEBAAAAAAAAAAAAAAAAAAABAQEBAQEBAQEBAQEBAQEBAQEAAAAAAAAAAAAAAAAAAAEBAQEBAQEBAQEBAQEBAQEBAQAAAAAAAAAAAAAAAAAAAQEBAQEBAQEBAQEBAAAAAAAAAAAAAAAAAAAAAAAAAAABAQEBAQEBAQEBAQEAAAAAAAAAAAAAAAAAAAAAAAAAAAEBAQEBAQEBAQEBAQAAAAAAAAAAAAAAAAAAAQEBAQEBAQEBAQEBAQEBAQEBAAAAAAAAAAAAAAAAAAABAQEBAQEBAQEBAQEBAQEBAQEAAAAAAAAAAAAAAAAAAAEBAQEBAQEBAQEBAQEBAQEBAQAAAAAAAAAAAAAAAAAAAQEBAQEBAQEBAQEBAQEBAQEBAAAAAAAAAAAAAAAAAAABAQEBAQEBAQEBAQEBAQEBAQEAAAAAAAAAAAAAAAAAAAEBAQEBAQEBAQEBAQ==" + }, + "palette" : { + "originalArgb8888" : [ -265674 ], + "convertedRgb565" : [ -122 ] } }, "diagnostics" : [ ] @@ -168,14 +168,14 @@ "last_modified" : 1774359772415, "fingerprint" : "eeb7cc665386299403b7be1c272375d5077f3647c587f8033aa8c9275f840562", "metadata" : { - "palette" : { - "originalArgb8888" : [ -265674 ], - "convertedRgb565" : [ -122 ] - }, "tile" : { "width" : 32, "height" : 32, "paletteIndices" : "AQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAAAAAAAAAAABAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEAAAAAAAAAAAEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQAAAAAAAAAAAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAAAAAAAAAAABAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEAAAAAAAAAAAEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQAAAAAAAAAAAQEBAQEBAQEBAQEBAAAAAAAAAAAAAAAAAAAAAAAAAAABAQEBAQEBAQEBAQEAAAAAAAAAAAAAAAAAAAAAAAAAAAEBAQEBAQEBAQEBAQAAAAAAAAAAAAAAAAAAAAAAAAAAAQEBAQEBAQEBAQEBAAAAAAAAAAAAAAAAAAAAAAAAAAABAQEBAQEBAQEBAQEAAAAAAAAAAAAAAAAAAAAAAAAAAAEBAQEBAQEBAQEBAQAAAAAAAAAAAAAAAAAAAAAAAAAAAQEBAQEBAQEBAQEBAAAAAAAAAAAAAAAAAAAAAAAAAAABAQEBAQEBAQEBAQEAAAAAAAAAAAAAAAAAAAAAAAAAAAEBAQEBAQEBAQEBAQAAAAAAAAAAAAAAAAAAAQEBAQEBAQEBAQEBAQEBAQEBAAAAAAAAAAAAAAAAAAABAQEBAQEBAQEBAQEBAQEBAQEAAAAAAAAAAAAAAAAAAAEBAQEBAQEBAQEBAQEBAQEBAQAAAAAAAAAAAAAAAAAAAQEBAQEBAQEBAQEBAAAAAAAAAAAAAAAAAAAAAAAAAAABAQEBAQEBAQEBAQEAAAAAAAAAAAAAAAAAAAAAAAAAAAEBAQEBAQEBAQEBAQAAAAAAAAAAAAAAAAAAAQEBAQEBAQEBAQEBAQEBAQEBAAAAAAAAAAAAAAAAAAABAQEBAQEBAQEBAQEBAQEBAQEAAAAAAAAAAAAAAAAAAAEBAQEBAQEBAQEBAQEBAQEBAQAAAAAAAAAAAAAAAAAAAQEBAQEBAQEBAQEBAQEBAQEBAAAAAAAAAAAAAAAAAAABAQEBAQEBAQEBAQEBAQEBAQEAAAAAAAAAAAAAAAAAAAEBAQEBAQEBAQEBAQ==" + }, + "palette" : { + "originalArgb8888" : [ -265674 ], + "convertedRgb565" : [ -122 ] } }, "diagnostics" : [ ] @@ -186,14 +186,14 @@ "last_modified" : 1774359772416, "fingerprint" : "eeb7cc665386299403b7be1c272375d5077f3647c587f8033aa8c9275f840562", "metadata" : { - "palette" : { - "originalArgb8888" : [ -265674 ], - "convertedRgb565" : [ -122 ] - }, "tile" : { "width" : 32, "height" : 32, "paletteIndices" : "AQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAAAAAAAAAAABAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEAAAAAAAAAAAEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQAAAAAAAAAAAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAAAAAAAAAAABAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEAAAAAAAAAAAEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQAAAAAAAAAAAQEBAQEBAQEBAQEBAAAAAAAAAAAAAAAAAAAAAAAAAAABAQEBAQEBAQEBAQEAAAAAAAAAAAAAAAAAAAAAAAAAAAEBAQEBAQEBAQEBAQAAAAAAAAAAAAAAAAAAAAAAAAAAAQEBAQEBAQEBAQEBAAAAAAAAAAAAAAAAAAAAAAAAAAABAQEBAQEBAQEBAQEAAAAAAAAAAAAAAAAAAAAAAAAAAAEBAQEBAQEBAQEBAQAAAAAAAAAAAAAAAAAAAAAAAAAAAQEBAQEBAQEBAQEBAAAAAAAAAAAAAAAAAAAAAAAAAAABAQEBAQEBAQEBAQEAAAAAAAAAAAAAAAAAAAAAAAAAAAEBAQEBAQEBAQEBAQAAAAAAAAAAAAAAAAAAAQEBAQEBAQEBAQEBAQEBAQEBAAAAAAAAAAAAAAAAAAABAQEBAQEBAQEBAQEBAQEBAQEAAAAAAAAAAAAAAAAAAAEBAQEBAQEBAQEBAQEBAQEBAQAAAAAAAAAAAAAAAAAAAQEBAQEBAQEBAQEBAAAAAAAAAAAAAAAAAAAAAAAAAAABAQEBAQEBAQEBAQEAAAAAAAAAAAAAAAAAAAAAAAAAAAEBAQEBAQEBAQEBAQAAAAAAAAAAAAAAAAAAAQEBAQEBAQEBAQEBAQEBAQEBAAAAAAAAAAAAAAAAAAABAQEBAQEBAQEBAQEBAQEBAQEAAAAAAAAAAAAAAAAAAAEBAQEBAQEBAQEBAQEBAQEBAQAAAAAAAAAAAAAAAAAAAQEBAQEBAQEBAQEBAQEBAQEBAAAAAAAAAAAAAAAAAAABAQEBAQEBAQEBAQEBAQEBAQEAAAAAAAAAAAAAAAAAAAEBAQEBAQEBAQEBAQ==" + }, + "palette" : { + "originalArgb8888" : [ -265674 ], + "convertedRgb565" : [ -122 ] } }, "diagnostics" : [ ] @@ -204,14 +204,14 @@ "last_modified" : 1774359772417, "fingerprint" : "eeb7cc665386299403b7be1c272375d5077f3647c587f8033aa8c9275f840562", "metadata" : { - "palette" : { - "originalArgb8888" : [ -265674 ], - "convertedRgb565" : [ -122 ] - }, "tile" : { "width" : 32, "height" : 32, "paletteIndices" : "AQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAAAAAAAAAAABAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEAAAAAAAAAAAEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQAAAAAAAAAAAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAAAAAAAAAAABAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEAAAAAAAAAAAEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQAAAAAAAAAAAQEBAQEBAQEBAQEBAAAAAAAAAAAAAAAAAAAAAAAAAAABAQEBAQEBAQEBAQEAAAAAAAAAAAAAAAAAAAAAAAAAAAEBAQEBAQEBAQEBAQAAAAAAAAAAAAAAAAAAAAAAAAAAAQEBAQEBAQEBAQEBAAAAAAAAAAAAAAAAAAAAAAAAAAABAQEBAQEBAQEBAQEAAAAAAAAAAAAAAAAAAAAAAAAAAAEBAQEBAQEBAQEBAQAAAAAAAAAAAAAAAAAAAAAAAAAAAQEBAQEBAQEBAQEBAAAAAAAAAAAAAAAAAAAAAAAAAAABAQEBAQEBAQEBAQEAAAAAAAAAAAAAAAAAAAAAAAAAAAEBAQEBAQEBAQEBAQAAAAAAAAAAAAAAAAAAAQEBAQEBAQEBAQEBAQEBAQEBAAAAAAAAAAAAAAAAAAABAQEBAQEBAQEBAQEBAQEBAQEAAAAAAAAAAAAAAAAAAAEBAQEBAQEBAQEBAQEBAQEBAQAAAAAAAAAAAAAAAAAAAQEBAQEBAQEBAQEBAAAAAAAAAAAAAAAAAAAAAAAAAAABAQEBAQEBAQEBAQEAAAAAAAAAAAAAAAAAAAAAAAAAAAEBAQEBAQEBAQEBAQAAAAAAAAAAAAAAAAAAAQEBAQEBAQEBAQEBAQEBAQEBAAAAAAAAAAAAAAAAAAABAQEBAQEBAQEBAQEBAQEBAQEAAAAAAAAAAAAAAAAAAAEBAQEBAQEBAQEBAQEBAQEBAQAAAAAAAAAAAAAAAAAAAQEBAQEBAQEBAQEBAQEBAQEBAAAAAAAAAAAAAAAAAAABAQEBAQEBAQEBAQEBAQEBAQEAAAAAAAAAAAAAAAAAAAEBAQEBAQEBAQEBAQ==" + }, + "palette" : { + "originalArgb8888" : [ -265674 ], + "convertedRgb565" : [ -122 ] } }, "diagnostics" : [ ] @@ -222,14 +222,14 @@ "last_modified" : 1774359772418, "fingerprint" : "eeb7cc665386299403b7be1c272375d5077f3647c587f8033aa8c9275f840562", "metadata" : { - "palette" : { - "originalArgb8888" : [ -265674 ], - "convertedRgb565" : [ -122 ] - }, "tile" : { "width" : 32, "height" : 32, "paletteIndices" : "AQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAAAAAAAAAAABAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEAAAAAAAAAAAEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQAAAAAAAAAAAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAAAAAAAAAAABAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEAAAAAAAAAAAEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQAAAAAAAAAAAQEBAQEBAQEBAQEBAAAAAAAAAAAAAAAAAAAAAAAAAAABAQEBAQEBAQEBAQEAAAAAAAAAAAAAAAAAAAAAAAAAAAEBAQEBAQEBAQEBAQAAAAAAAAAAAAAAAAAAAAAAAAAAAQEBAQEBAQEBAQEBAAAAAAAAAAAAAAAAAAAAAAAAAAABAQEBAQEBAQEBAQEAAAAAAAAAAAAAAAAAAAAAAAAAAAEBAQEBAQEBAQEBAQAAAAAAAAAAAAAAAAAAAAAAAAAAAQEBAQEBAQEBAQEBAAAAAAAAAAAAAAAAAAAAAAAAAAABAQEBAQEBAQEBAQEAAAAAAAAAAAAAAAAAAAAAAAAAAAEBAQEBAQEBAQEBAQAAAAAAAAAAAAAAAAAAAQEBAQEBAQEBAQEBAQEBAQEBAAAAAAAAAAAAAAAAAAABAQEBAQEBAQEBAQEBAQEBAQEAAAAAAAAAAAAAAAAAAAEBAQEBAQEBAQEBAQEBAQEBAQAAAAAAAAAAAAAAAAAAAQEBAQEBAQEBAQEBAAAAAAAAAAAAAAAAAAAAAAAAAAABAQEBAQEBAQEBAQEAAAAAAAAAAAAAAAAAAAAAAAAAAAEBAQEBAQEBAQEBAQAAAAAAAAAAAAAAAAAAAQEBAQEBAQEBAQEBAQEBAQEBAAAAAAAAAAAAAAAAAAABAQEBAQEBAQEBAQEBAQEBAQEAAAAAAAAAAAAAAAAAAAEBAQEBAQEBAQEBAQEBAQEBAQAAAAAAAAAAAAAAAAAAAQEBAQEBAQEBAQEBAQEBAQEBAAAAAAAAAAAAAAAAAAABAQEBAQEBAQEBAQEBAQEBAQEAAAAAAAAAAAAAAAAAAAEBAQEBAQEBAQEBAQ==" + }, + "palette" : { + "originalArgb8888" : [ -265674 ], + "convertedRgb565" : [ -122 ] } }, "diagnostics" : [ ] @@ -240,14 +240,14 @@ "last_modified" : 1774359772420, "fingerprint" : "eeb7cc665386299403b7be1c272375d5077f3647c587f8033aa8c9275f840562", "metadata" : { - "palette" : { - "originalArgb8888" : [ -265674 ], - "convertedRgb565" : [ -122 ] - }, "tile" : { "width" : 32, "height" : 32, "paletteIndices" : "AQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAAAAAAAAAAABAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEAAAAAAAAAAAEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQAAAAAAAAAAAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAAAAAAAAAAABAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEAAAAAAAAAAAEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQAAAAAAAAAAAQEBAQEBAQEBAQEBAAAAAAAAAAAAAAAAAAAAAAAAAAABAQEBAQEBAQEBAQEAAAAAAAAAAAAAAAAAAAAAAAAAAAEBAQEBAQEBAQEBAQAAAAAAAAAAAAAAAAAAAAAAAAAAAQEBAQEBAQEBAQEBAAAAAAAAAAAAAAAAAAAAAAAAAAABAQEBAQEBAQEBAQEAAAAAAAAAAAAAAAAAAAAAAAAAAAEBAQEBAQEBAQEBAQAAAAAAAAAAAAAAAAAAAAAAAAAAAQEBAQEBAQEBAQEBAAAAAAAAAAAAAAAAAAAAAAAAAAABAQEBAQEBAQEBAQEAAAAAAAAAAAAAAAAAAAAAAAAAAAEBAQEBAQEBAQEBAQAAAAAAAAAAAAAAAAAAAQEBAQEBAQEBAQEBAQEBAQEBAAAAAAAAAAAAAAAAAAABAQEBAQEBAQEBAQEBAQEBAQEAAAAAAAAAAAAAAAAAAAEBAQEBAQEBAQEBAQEBAQEBAQAAAAAAAAAAAAAAAAAAAQEBAQEBAQEBAQEBAAAAAAAAAAAAAAAAAAAAAAAAAAABAQEBAQEBAQEBAQEAAAAAAAAAAAAAAAAAAAAAAAAAAAEBAQEBAQEBAQEBAQAAAAAAAAAAAAAAAAAAAQEBAQEBAQEBAQEBAQEBAQEBAAAAAAAAAAAAAAAAAAABAQEBAQEBAQEBAQEBAQEBAQEAAAAAAAAAAAAAAAAAAAEBAQEBAQEBAQEBAQEBAQEBAQAAAAAAAAAAAAAAAAAAAQEBAQEBAQEBAQEBAQEBAQEBAAAAAAAAAAAAAAAAAAABAQEBAQEBAQEBAQEBAQEBAQEAAAAAAAAAAAAAAAAAAAEBAQEBAQEBAQEBAQ==" + }, + "palette" : { + "originalArgb8888" : [ -265674 ], + "convertedRgb565" : [ -122 ] } }, "diagnostics" : [ ] @@ -258,14 +258,14 @@ "last_modified" : 1774359772421, "fingerprint" : "eeb7cc665386299403b7be1c272375d5077f3647c587f8033aa8c9275f840562", "metadata" : { - "palette" : { - "originalArgb8888" : [ -265674 ], - "convertedRgb565" : [ -122 ] - }, "tile" : { "width" : 32, "height" : 32, "paletteIndices" : "AQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAAAAAAAAAAABAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEAAAAAAAAAAAEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQAAAAAAAAAAAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAAAAAAAAAAABAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEAAAAAAAAAAAEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQAAAAAAAAAAAQEBAQEBAQEBAQEBAAAAAAAAAAAAAAAAAAAAAAAAAAABAQEBAQEBAQEBAQEAAAAAAAAAAAAAAAAAAAAAAAAAAAEBAQEBAQEBAQEBAQAAAAAAAAAAAAAAAAAAAAAAAAAAAQEBAQEBAQEBAQEBAAAAAAAAAAAAAAAAAAAAAAAAAAABAQEBAQEBAQEBAQEAAAAAAAAAAAAAAAAAAAAAAAAAAAEBAQEBAQEBAQEBAQAAAAAAAAAAAAAAAAAAAAAAAAAAAQEBAQEBAQEBAQEBAAAAAAAAAAAAAAAAAAAAAAAAAAABAQEBAQEBAQEBAQEAAAAAAAAAAAAAAAAAAAAAAAAAAAEBAQEBAQEBAQEBAQAAAAAAAAAAAAAAAAAAAQEBAQEBAQEBAQEBAQEBAQEBAAAAAAAAAAAAAAAAAAABAQEBAQEBAQEBAQEBAQEBAQEAAAAAAAAAAAAAAAAAAAEBAQEBAQEBAQEBAQEBAQEBAQAAAAAAAAAAAAAAAAAAAQEBAQEBAQEBAQEBAAAAAAAAAAAAAAAAAAAAAAAAAAABAQEBAQEBAQEBAQEAAAAAAAAAAAAAAAAAAAAAAAAAAAEBAQEBAQEBAQEBAQAAAAAAAAAAAAAAAAAAAQEBAQEBAQEBAQEBAQEBAQEBAAAAAAAAAAAAAAAAAAABAQEBAQEBAQEBAQEBAQEBAQEAAAAAAAAAAAAAAAAAAAEBAQEBAQEBAQEBAQEBAQEBAQAAAAAAAAAAAAAAAAAAAQEBAQEBAQEBAQEBAQEBAQEBAAAAAAAAAAAAAAAAAAABAQEBAQEBAQEBAQEBAQEBAQEAAAAAAAAAAAAAAAAAAAEBAQEBAQEBAQEBAQ==" + }, + "palette" : { + "originalArgb8888" : [ -265674 ], + "convertedRgb565" : [ -122 ] } }, "diagnostics" : [ ] @@ -276,14 +276,14 @@ "last_modified" : 1774359772423, "fingerprint" : "eeb7cc665386299403b7be1c272375d5077f3647c587f8033aa8c9275f840562", "metadata" : { - "palette" : { - "originalArgb8888" : [ -265674 ], - "convertedRgb565" : [ -122 ] - }, "tile" : { "width" : 32, "height" : 32, "paletteIndices" : "AQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAAAAAAAAAAABAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEAAAAAAAAAAAEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQAAAAAAAAAAAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAAAAAAAAAAABAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEAAAAAAAAAAAEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQAAAAAAAAAAAQEBAQEBAQEBAQEBAAAAAAAAAAAAAAAAAAAAAAAAAAABAQEBAQEBAQEBAQEAAAAAAAAAAAAAAAAAAAAAAAAAAAEBAQEBAQEBAQEBAQAAAAAAAAAAAAAAAAAAAAAAAAAAAQEBAQEBAQEBAQEBAAAAAAAAAAAAAAAAAAAAAAAAAAABAQEBAQEBAQEBAQEAAAAAAAAAAAAAAAAAAAAAAAAAAAEBAQEBAQEBAQEBAQAAAAAAAAAAAAAAAAAAAAAAAAAAAQEBAQEBAQEBAQEBAAAAAAAAAAAAAAAAAAAAAAAAAAABAQEBAQEBAQEBAQEAAAAAAAAAAAAAAAAAAAAAAAAAAAEBAQEBAQEBAQEBAQAAAAAAAAAAAAAAAAAAAQEBAQEBAQEBAQEBAQEBAQEBAAAAAAAAAAAAAAAAAAABAQEBAQEBAQEBAQEBAQEBAQEAAAAAAAAAAAAAAAAAAAEBAQEBAQEBAQEBAQEBAQEBAQAAAAAAAAAAAAAAAAAAAQEBAQEBAQEBAQEBAAAAAAAAAAAAAAAAAAAAAAAAAAABAQEBAQEBAQEBAQEAAAAAAAAAAAAAAAAAAAAAAAAAAAEBAQEBAQEBAQEBAQAAAAAAAAAAAAAAAAAAAQEBAQEBAQEBAQEBAQEBAQEBAAAAAAAAAAAAAAAAAAABAQEBAQEBAQEBAQEBAQEBAQEAAAAAAAAAAAAAAAAAAAEBAQEBAQEBAQEBAQEBAQEBAQAAAAAAAAAAAAAAAAAAAQEBAQEBAQEBAQEBAQEBAQEBAAAAAAAAAAAAAAAAAAABAQEBAQEBAQEBAQEBAQEBAQEAAAAAAAAAAAAAAAAAAAEBAQEBAQEBAQEBAQ==" + }, + "palette" : { + "originalArgb8888" : [ -265674 ], + "convertedRgb565" : [ -122 ] } }, "diagnostics" : [ ] @@ -294,14 +294,14 @@ "last_modified" : 1774359772424, "fingerprint" : "eeb7cc665386299403b7be1c272375d5077f3647c587f8033aa8c9275f840562", "metadata" : { - "palette" : { - "originalArgb8888" : [ -265674 ], - "convertedRgb565" : [ -122 ] - }, "tile" : { "width" : 32, "height" : 32, "paletteIndices" : "AQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAAAAAAAAAAABAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEAAAAAAAAAAAEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQAAAAAAAAAAAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAAAAAAAAAAABAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEAAAAAAAAAAAEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQAAAAAAAAAAAQEBAQEBAQEBAQEBAAAAAAAAAAAAAAAAAAAAAAAAAAABAQEBAQEBAQEBAQEAAAAAAAAAAAAAAAAAAAAAAAAAAAEBAQEBAQEBAQEBAQAAAAAAAAAAAAAAAAAAAAAAAAAAAQEBAQEBAQEBAQEBAAAAAAAAAAAAAAAAAAAAAAAAAAABAQEBAQEBAQEBAQEAAAAAAAAAAAAAAAAAAAAAAAAAAAEBAQEBAQEBAQEBAQAAAAAAAAAAAAAAAAAAAAAAAAAAAQEBAQEBAQEBAQEBAAAAAAAAAAAAAAAAAAAAAAAAAAABAQEBAQEBAQEBAQEAAAAAAAAAAAAAAAAAAAAAAAAAAAEBAQEBAQEBAQEBAQAAAAAAAAAAAAAAAAAAAQEBAQEBAQEBAQEBAQEBAQEBAAAAAAAAAAAAAAAAAAABAQEBAQEBAQEBAQEBAQEBAQEAAAAAAAAAAAAAAAAAAAEBAQEBAQEBAQEBAQEBAQEBAQAAAAAAAAAAAAAAAAAAAQEBAQEBAQEBAQEBAAAAAAAAAAAAAAAAAAAAAAAAAAABAQEBAQEBAQEBAQEAAAAAAAAAAAAAAAAAAAAAAAAAAAEBAQEBAQEBAQEBAQAAAAAAAAAAAAAAAAAAAQEBAQEBAQEBAQEBAQEBAQEBAAAAAAAAAAAAAAAAAAABAQEBAQEBAQEBAQEBAQEBAQEAAAAAAAAAAAAAAAAAAAEBAQEBAQEBAQEBAQEBAQEBAQAAAAAAAAAAAAAAAAAAAQEBAQEBAQEBAQEBAQEBAQEBAAAAAAAAAAAAAAAAAAABAQEBAQEBAQEBAQEBAQEBAQEAAAAAAAAAAAAAAAAAAAEBAQEBAQEBAQEBAQ==" + }, + "palette" : { + "originalArgb8888" : [ -265674 ], + "convertedRgb565" : [ -122 ] } }, "diagnostics" : [ ] @@ -312,14 +312,14 @@ "last_modified" : 1774359772425, "fingerprint" : "eeb7cc665386299403b7be1c272375d5077f3647c587f8033aa8c9275f840562", "metadata" : { - "palette" : { - "originalArgb8888" : [ -265674 ], - "convertedRgb565" : [ -122 ] - }, "tile" : { "width" : 32, "height" : 32, "paletteIndices" : "AQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAAAAAAAAAAABAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEAAAAAAAAAAAEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQAAAAAAAAAAAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAAAAAAAAAAABAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEAAAAAAAAAAAEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQAAAAAAAAAAAQEBAQEBAQEBAQEBAAAAAAAAAAAAAAAAAAAAAAAAAAABAQEBAQEBAQEBAQEAAAAAAAAAAAAAAAAAAAAAAAAAAAEBAQEBAQEBAQEBAQAAAAAAAAAAAAAAAAAAAAAAAAAAAQEBAQEBAQEBAQEBAAAAAAAAAAAAAAAAAAAAAAAAAAABAQEBAQEBAQEBAQEAAAAAAAAAAAAAAAAAAAAAAAAAAAEBAQEBAQEBAQEBAQAAAAAAAAAAAAAAAAAAAAAAAAAAAQEBAQEBAQEBAQEBAAAAAAAAAAAAAAAAAAAAAAAAAAABAQEBAQEBAQEBAQEAAAAAAAAAAAAAAAAAAAAAAAAAAAEBAQEBAQEBAQEBAQAAAAAAAAAAAAAAAAAAAQEBAQEBAQEBAQEBAQEBAQEBAAAAAAAAAAAAAAAAAAABAQEBAQEBAQEBAQEBAQEBAQEAAAAAAAAAAAAAAAAAAAEBAQEBAQEBAQEBAQEBAQEBAQAAAAAAAAAAAAAAAAAAAQEBAQEBAQEBAQEBAAAAAAAAAAAAAAAAAAAAAAAAAAABAQEBAQEBAQEBAQEAAAAAAAAAAAAAAAAAAAAAAAAAAAEBAQEBAQEBAQEBAQAAAAAAAAAAAAAAAAAAAQEBAQEBAQEBAQEBAQEBAQEBAAAAAAAAAAAAAAAAAAABAQEBAQEBAQEBAQEBAQEBAQEAAAAAAAAAAAAAAAAAAAEBAQEBAQEBAQEBAQEBAQEBAQAAAAAAAAAAAAAAAAAAAQEBAQEBAQEBAQEBAQEBAQEBAAAAAAAAAAAAAAAAAAABAQEBAQEBAQEBAQEBAQEBAQEAAAAAAAAAAAAAAAAAAAEBAQEBAQEBAQEBAQ==" + }, + "palette" : { + "originalArgb8888" : [ -265674 ], + "convertedRgb565" : [ -122 ] } }, "diagnostics" : [ ] @@ -330,14 +330,14 @@ "last_modified" : 1774359772426, "fingerprint" : "eeb7cc665386299403b7be1c272375d5077f3647c587f8033aa8c9275f840562", "metadata" : { - "palette" : { - "originalArgb8888" : [ -265674 ], - "convertedRgb565" : [ -122 ] - }, "tile" : { "width" : 32, "height" : 32, "paletteIndices" : "AQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAAAAAAAAAAABAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEAAAAAAAAAAAEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQAAAAAAAAAAAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAAAAAAAAAAABAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEAAAAAAAAAAAEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQAAAAAAAAAAAQEBAQEBAQEBAQEBAAAAAAAAAAAAAAAAAAAAAAAAAAABAQEBAQEBAQEBAQEAAAAAAAAAAAAAAAAAAAAAAAAAAAEBAQEBAQEBAQEBAQAAAAAAAAAAAAAAAAAAAAAAAAAAAQEBAQEBAQEBAQEBAAAAAAAAAAAAAAAAAAAAAAAAAAABAQEBAQEBAQEBAQEAAAAAAAAAAAAAAAAAAAAAAAAAAAEBAQEBAQEBAQEBAQAAAAAAAAAAAAAAAAAAAAAAAAAAAQEBAQEBAQEBAQEBAAAAAAAAAAAAAAAAAAAAAAAAAAABAQEBAQEBAQEBAQEAAAAAAAAAAAAAAAAAAAAAAAAAAAEBAQEBAQEBAQEBAQAAAAAAAAAAAAAAAAAAAQEBAQEBAQEBAQEBAQEBAQEBAAAAAAAAAAAAAAAAAAABAQEBAQEBAQEBAQEBAQEBAQEAAAAAAAAAAAAAAAAAAAEBAQEBAQEBAQEBAQEBAQEBAQAAAAAAAAAAAAAAAAAAAQEBAQEBAQEBAQEBAAAAAAAAAAAAAAAAAAAAAAAAAAABAQEBAQEBAQEBAQEAAAAAAAAAAAAAAAAAAAAAAAAAAAEBAQEBAQEBAQEBAQAAAAAAAAAAAAAAAAAAAQEBAQEBAQEBAQEBAQEBAQEBAAAAAAAAAAAAAAAAAAABAQEBAQEBAQEBAQEBAQEBAQEAAAAAAAAAAAAAAAAAAAEBAQEBAQEBAQEBAQEBAQEBAQAAAAAAAAAAAAAAAAAAAQEBAQEBAQEBAQEBAQEBAQEBAAAAAAAAAAAAAAAAAAABAQEBAQEBAQEBAQEBAQEBAQEAAAAAAAAAAAAAAAAAAAEBAQEBAQEBAQEBAQ==" + }, + "palette" : { + "originalArgb8888" : [ -265674 ], + "convertedRgb565" : [ -122 ] } }, "diagnostics" : [ ] @@ -348,14 +348,14 @@ "last_modified" : 1774359772428, "fingerprint" : "eeb7cc665386299403b7be1c272375d5077f3647c587f8033aa8c9275f840562", "metadata" : { - "palette" : { - "originalArgb8888" : [ -265674 ], - "convertedRgb565" : [ -122 ] - }, "tile" : { "width" : 32, "height" : 32, "paletteIndices" : "AQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAAAAAAAAAAABAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEAAAAAAAAAAAEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQAAAAAAAAAAAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAAAAAAAAAAABAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEAAAAAAAAAAAEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQAAAAAAAAAAAQEBAQEBAQEBAQEBAAAAAAAAAAAAAAAAAAAAAAAAAAABAQEBAQEBAQEBAQEAAAAAAAAAAAAAAAAAAAAAAAAAAAEBAQEBAQEBAQEBAQAAAAAAAAAAAAAAAAAAAAAAAAAAAQEBAQEBAQEBAQEBAAAAAAAAAAAAAAAAAAAAAAAAAAABAQEBAQEBAQEBAQEAAAAAAAAAAAAAAAAAAAAAAAAAAAEBAQEBAQEBAQEBAQAAAAAAAAAAAAAAAAAAAAAAAAAAAQEBAQEBAQEBAQEBAAAAAAAAAAAAAAAAAAAAAAAAAAABAQEBAQEBAQEBAQEAAAAAAAAAAAAAAAAAAAAAAAAAAAEBAQEBAQEBAQEBAQAAAAAAAAAAAAAAAAAAAQEBAQEBAQEBAQEBAQEBAQEBAAAAAAAAAAAAAAAAAAABAQEBAQEBAQEBAQEBAQEBAQEAAAAAAAAAAAAAAAAAAAEBAQEBAQEBAQEBAQEBAQEBAQAAAAAAAAAAAAAAAAAAAQEBAQEBAQEBAQEBAAAAAAAAAAAAAAAAAAAAAAAAAAABAQEBAQEBAQEBAQEAAAAAAAAAAAAAAAAAAAAAAAAAAAEBAQEBAQEBAQEBAQAAAAAAAAAAAAAAAAAAAQEBAQEBAQEBAQEBAQEBAQEBAAAAAAAAAAAAAAAAAAABAQEBAQEBAQEBAQEBAQEBAQEAAAAAAAAAAAAAAAAAAAEBAQEBAQEBAQEBAQEBAQEBAQAAAAAAAAAAAAAAAAAAAQEBAQEBAQEBAQEBAQEBAQEBAAAAAAAAAAAAAAAAAAABAQEBAQEBAQEBAQEBAQEBAQEAAAAAAAAAAAAAAAAAAAEBAQEBAQEBAQEBAQ==" + }, + "palette" : { + "originalArgb8888" : [ -265674 ], + "convertedRgb565" : [ -122 ] } }, "diagnostics" : [ ] @@ -366,14 +366,14 @@ "last_modified" : 1774359772429, "fingerprint" : "eeb7cc665386299403b7be1c272375d5077f3647c587f8033aa8c9275f840562", "metadata" : { - "palette" : { - "originalArgb8888" : [ -265674 ], - "convertedRgb565" : [ -122 ] - }, "tile" : { "width" : 32, "height" : 32, "paletteIndices" : "AQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAAAAAAAAAAABAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEAAAAAAAAAAAEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQAAAAAAAAAAAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAAAAAAAAAAABAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEAAAAAAAAAAAEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQAAAAAAAAAAAQEBAQEBAQEBAQEBAAAAAAAAAAAAAAAAAAAAAAAAAAABAQEBAQEBAQEBAQEAAAAAAAAAAAAAAAAAAAAAAAAAAAEBAQEBAQEBAQEBAQAAAAAAAAAAAAAAAAAAAAAAAAAAAQEBAQEBAQEBAQEBAAAAAAAAAAAAAAAAAAAAAAAAAAABAQEBAQEBAQEBAQEAAAAAAAAAAAAAAAAAAAAAAAAAAAEBAQEBAQEBAQEBAQAAAAAAAAAAAAAAAAAAAAAAAAAAAQEBAQEBAQEBAQEBAAAAAAAAAAAAAAAAAAAAAAAAAAABAQEBAQEBAQEBAQEAAAAAAAAAAAAAAAAAAAAAAAAAAAEBAQEBAQEBAQEBAQAAAAAAAAAAAAAAAAAAAQEBAQEBAQEBAQEBAQEBAQEBAAAAAAAAAAAAAAAAAAABAQEBAQEBAQEBAQEBAQEBAQEAAAAAAAAAAAAAAAAAAAEBAQEBAQEBAQEBAQEBAQEBAQAAAAAAAAAAAAAAAAAAAQEBAQEBAQEBAQEBAAAAAAAAAAAAAAAAAAAAAAAAAAABAQEBAQEBAQEBAQEAAAAAAAAAAAAAAAAAAAAAAAAAAAEBAQEBAQEBAQEBAQAAAAAAAAAAAAAAAAAAAQEBAQEBAQEBAQEBAQEBAQEBAAAAAAAAAAAAAAAAAAABAQEBAQEBAQEBAQEBAQEBAQEAAAAAAAAAAAAAAAAAAAEBAQEBAQEBAQEBAQEBAQEBAQAAAAAAAAAAAAAAAAAAAQEBAQEBAQEBAQEBAQEBAQEBAAAAAAAAAAAAAAAAAAABAQEBAQEBAQEBAQEBAQEBAQEAAAAAAAAAAAAAAAAAAAEBAQEBAQEBAQEBAQ==" + }, + "palette" : { + "originalArgb8888" : [ -265674 ], + "convertedRgb565" : [ -122 ] } }, "diagnostics" : [ ] @@ -384,14 +384,14 @@ "last_modified" : 1774359772430, "fingerprint" : "eeb7cc665386299403b7be1c272375d5077f3647c587f8033aa8c9275f840562", "metadata" : { - "palette" : { - "originalArgb8888" : [ -265674 ], - "convertedRgb565" : [ -122 ] - }, "tile" : { "width" : 32, "height" : 32, "paletteIndices" : "AQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAAAAAAAAAAABAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEAAAAAAAAAAAEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQAAAAAAAAAAAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAAAAAAAAAAABAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEAAAAAAAAAAAEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQAAAAAAAAAAAQEBAQEBAQEBAQEBAAAAAAAAAAAAAAAAAAAAAAAAAAABAQEBAQEBAQEBAQEAAAAAAAAAAAAAAAAAAAAAAAAAAAEBAQEBAQEBAQEBAQAAAAAAAAAAAAAAAAAAAAAAAAAAAQEBAQEBAQEBAQEBAAAAAAAAAAAAAAAAAAAAAAAAAAABAQEBAQEBAQEBAQEAAAAAAAAAAAAAAAAAAAAAAAAAAAEBAQEBAQEBAQEBAQAAAAAAAAAAAAAAAAAAAAAAAAAAAQEBAQEBAQEBAQEBAAAAAAAAAAAAAAAAAAAAAAAAAAABAQEBAQEBAQEBAQEAAAAAAAAAAAAAAAAAAAAAAAAAAAEBAQEBAQEBAQEBAQAAAAAAAAAAAAAAAAAAAQEBAQEBAQEBAQEBAQEBAQEBAAAAAAAAAAAAAAAAAAABAQEBAQEBAQEBAQEBAQEBAQEAAAAAAAAAAAAAAAAAAAEBAQEBAQEBAQEBAQEBAQEBAQAAAAAAAAAAAAAAAAAAAQEBAQEBAQEBAQEBAAAAAAAAAAAAAAAAAAAAAAAAAAABAQEBAQEBAQEBAQEAAAAAAAAAAAAAAAAAAAAAAAAAAAEBAQEBAQEBAQEBAQAAAAAAAAAAAAAAAAAAAQEBAQEBAQEBAQEBAQEBAQEBAAAAAAAAAAAAAAAAAAABAQEBAQEBAQEBAQEBAQEBAQEAAAAAAAAAAAAAAAAAAAEBAQEBAQEBAQEBAQEBAQEBAQAAAAAAAAAAAAAAAAAAAQEBAQEBAQEBAQEBAQEBAQEBAAAAAAAAAAAAAAAAAAABAQEBAQEBAQEBAQEBAQEBAQEAAAAAAAAAAAAAAAAAAAEBAQEBAQEBAQEBAQ==" + }, + "palette" : { + "originalArgb8888" : [ -265674 ], + "convertedRgb565" : [ -122 ] } }, "diagnostics" : [ ] @@ -402,14 +402,14 @@ "last_modified" : 1774359772431, "fingerprint" : "eeb7cc665386299403b7be1c272375d5077f3647c587f8033aa8c9275f840562", "metadata" : { - "palette" : { - "originalArgb8888" : [ -265674 ], - "convertedRgb565" : [ -122 ] - }, "tile" : { "width" : 32, "height" : 32, "paletteIndices" : "AQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAAAAAAAAAAABAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEAAAAAAAAAAAEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQAAAAAAAAAAAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAAAAAAAAAAABAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEAAAAAAAAAAAEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQAAAAAAAAAAAQEBAQEBAQEBAQEBAAAAAAAAAAAAAAAAAAAAAAAAAAABAQEBAQEBAQEBAQEAAAAAAAAAAAAAAAAAAAAAAAAAAAEBAQEBAQEBAQEBAQAAAAAAAAAAAAAAAAAAAAAAAAAAAQEBAQEBAQEBAQEBAAAAAAAAAAAAAAAAAAAAAAAAAAABAQEBAQEBAQEBAQEAAAAAAAAAAAAAAAAAAAAAAAAAAAEBAQEBAQEBAQEBAQAAAAAAAAAAAAAAAAAAAAAAAAAAAQEBAQEBAQEBAQEBAAAAAAAAAAAAAAAAAAAAAAAAAAABAQEBAQEBAQEBAQEAAAAAAAAAAAAAAAAAAAAAAAAAAAEBAQEBAQEBAQEBAQAAAAAAAAAAAAAAAAAAAQEBAQEBAQEBAQEBAQEBAQEBAAAAAAAAAAAAAAAAAAABAQEBAQEBAQEBAQEBAQEBAQEAAAAAAAAAAAAAAAAAAAEBAQEBAQEBAQEBAQEBAQEBAQAAAAAAAAAAAAAAAAAAAQEBAQEBAQEBAQEBAAAAAAAAAAAAAAAAAAAAAAAAAAABAQEBAQEBAQEBAQEAAAAAAAAAAAAAAAAAAAAAAAAAAAEBAQEBAQEBAQEBAQAAAAAAAAAAAAAAAAAAAQEBAQEBAQEBAQEBAQEBAQEBAAAAAAAAAAAAAAAAAAABAQEBAQEBAQEBAQEBAQEBAQEAAAAAAAAAAAAAAAAAAAEBAQEBAQEBAQEBAQEBAQEBAQAAAAAAAAAAAAAAAAAAAQEBAQEBAQEBAQEBAQEBAQEBAAAAAAAAAAAAAAAAAAABAQEBAQEBAQEBAQEBAQEBAQEAAAAAAAAAAAAAAAAAAAEBAQEBAQEBAQEBAQ==" + }, + "palette" : { + "originalArgb8888" : [ -265674 ], + "convertedRgb565" : [ -122 ] } }, "diagnostics" : [ ] @@ -420,14 +420,14 @@ "last_modified" : 1774359772432, "fingerprint" : "eeb7cc665386299403b7be1c272375d5077f3647c587f8033aa8c9275f840562", "metadata" : { - "palette" : { - "originalArgb8888" : [ -265674 ], - "convertedRgb565" : [ -122 ] - }, "tile" : { "width" : 32, "height" : 32, "paletteIndices" : "AQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAAAAAAAAAAABAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEAAAAAAAAAAAEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQAAAAAAAAAAAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAAAAAAAAAAABAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEAAAAAAAAAAAEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQAAAAAAAAAAAQEBAQEBAQEBAQEBAAAAAAAAAAAAAAAAAAAAAAAAAAABAQEBAQEBAQEBAQEAAAAAAAAAAAAAAAAAAAAAAAAAAAEBAQEBAQEBAQEBAQAAAAAAAAAAAAAAAAAAAAAAAAAAAQEBAQEBAQEBAQEBAAAAAAAAAAAAAAAAAAAAAAAAAAABAQEBAQEBAQEBAQEAAAAAAAAAAAAAAAAAAAAAAAAAAAEBAQEBAQEBAQEBAQAAAAAAAAAAAAAAAAAAAAAAAAAAAQEBAQEBAQEBAQEBAAAAAAAAAAAAAAAAAAAAAAAAAAABAQEBAQEBAQEBAQEAAAAAAAAAAAAAAAAAAAAAAAAAAAEBAQEBAQEBAQEBAQAAAAAAAAAAAAAAAAAAAQEBAQEBAQEBAQEBAQEBAQEBAAAAAAAAAAAAAAAAAAABAQEBAQEBAQEBAQEBAQEBAQEAAAAAAAAAAAAAAAAAAAEBAQEBAQEBAQEBAQEBAQEBAQAAAAAAAAAAAAAAAAAAAQEBAQEBAQEBAQEBAAAAAAAAAAAAAAAAAAAAAAAAAAABAQEBAQEBAQEBAQEAAAAAAAAAAAAAAAAAAAAAAAAAAAEBAQEBAQEBAQEBAQAAAAAAAAAAAAAAAAAAAQEBAQEBAQEBAQEBAQEBAQEBAAAAAAAAAAAAAAAAAAABAQEBAQEBAQEBAQEBAQEBAQEAAAAAAAAAAAAAAAAAAAEBAQEBAQEBAQEBAQEBAQEBAQAAAAAAAAAAAAAAAAAAAQEBAQEBAQEBAQEBAQEBAQEBAAAAAAAAAAAAAAAAAAABAQEBAQEBAQEBAQEBAQEBAQEAAAAAAAAAAAAAAAAAAAEBAQEBAQEBAQEBAQ==" + }, + "palette" : { + "originalArgb8888" : [ -265674 ], + "convertedRgb565" : [ -122 ] } }, "diagnostics" : [ ] @@ -438,14 +438,14 @@ "last_modified" : 1774359772433, "fingerprint" : "eeb7cc665386299403b7be1c272375d5077f3647c587f8033aa8c9275f840562", "metadata" : { - "palette" : { - "originalArgb8888" : [ -265674 ], - "convertedRgb565" : [ -122 ] - }, "tile" : { "width" : 32, "height" : 32, "paletteIndices" : "AQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAAAAAAAAAAABAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEAAAAAAAAAAAEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQAAAAAAAAAAAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAAAAAAAAAAABAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEAAAAAAAAAAAEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQAAAAAAAAAAAQEBAQEBAQEBAQEBAAAAAAAAAAAAAAAAAAAAAAAAAAABAQEBAQEBAQEBAQEAAAAAAAAAAAAAAAAAAAAAAAAAAAEBAQEBAQEBAQEBAQAAAAAAAAAAAAAAAAAAAAAAAAAAAQEBAQEBAQEBAQEBAAAAAAAAAAAAAAAAAAAAAAAAAAABAQEBAQEBAQEBAQEAAAAAAAAAAAAAAAAAAAAAAAAAAAEBAQEBAQEBAQEBAQAAAAAAAAAAAAAAAAAAAAAAAAAAAQEBAQEBAQEBAQEBAAAAAAAAAAAAAAAAAAAAAAAAAAABAQEBAQEBAQEBAQEAAAAAAAAAAAAAAAAAAAAAAAAAAAEBAQEBAQEBAQEBAQAAAAAAAAAAAAAAAAAAAQEBAQEBAQEBAQEBAQEBAQEBAAAAAAAAAAAAAAAAAAABAQEBAQEBAQEBAQEBAQEBAQEAAAAAAAAAAAAAAAAAAAEBAQEBAQEBAQEBAQEBAQEBAQAAAAAAAAAAAAAAAAAAAQEBAQEBAQEBAQEBAAAAAAAAAAAAAAAAAAAAAAAAAAABAQEBAQEBAQEBAQEAAAAAAAAAAAAAAAAAAAAAAAAAAAEBAQEBAQEBAQEBAQAAAAAAAAAAAAAAAAAAAQEBAQEBAQEBAQEBAQEBAQEBAAAAAAAAAAAAAAAAAAABAQEBAQEBAQEBAQEBAQEBAQEAAAAAAAAAAAAAAAAAAAEBAQEBAQEBAQEBAQEBAQEBAQAAAAAAAAAAAAAAAAAAAQEBAQEBAQEBAQEBAQEBAQEBAAAAAAAAAAAAAAAAAAABAQEBAQEBAQEBAQEBAQEBAQEAAAAAAAAAAAAAAAAAAAEBAQEBAQEBAQEBAQ==" + }, + "palette" : { + "originalArgb8888" : [ -265674 ], + "convertedRgb565" : [ -122 ] } }, "diagnostics" : [ ] @@ -456,14 +456,14 @@ "last_modified" : 1774359772435, "fingerprint" : "eeb7cc665386299403b7be1c272375d5077f3647c587f8033aa8c9275f840562", "metadata" : { - "palette" : { - "originalArgb8888" : [ -265674 ], - "convertedRgb565" : [ -122 ] - }, "tile" : { "width" : 32, "height" : 32, "paletteIndices" : "AQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAAAAAAAAAAABAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEAAAAAAAAAAAEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQAAAAAAAAAAAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAAAAAAAAAAABAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEAAAAAAAAAAAEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQAAAAAAAAAAAQEBAQEBAQEBAQEBAAAAAAAAAAAAAAAAAAAAAAAAAAABAQEBAQEBAQEBAQEAAAAAAAAAAAAAAAAAAAAAAAAAAAEBAQEBAQEBAQEBAQAAAAAAAAAAAAAAAAAAAAAAAAAAAQEBAQEBAQEBAQEBAAAAAAAAAAAAAAAAAAAAAAAAAAABAQEBAQEBAQEBAQEAAAAAAAAAAAAAAAAAAAAAAAAAAAEBAQEBAQEBAQEBAQAAAAAAAAAAAAAAAAAAAAAAAAAAAQEBAQEBAQEBAQEBAAAAAAAAAAAAAAAAAAAAAAAAAAABAQEBAQEBAQEBAQEAAAAAAAAAAAAAAAAAAAAAAAAAAAEBAQEBAQEBAQEBAQAAAAAAAAAAAAAAAAAAAQEBAQEBAQEBAQEBAQEBAQEBAAAAAAAAAAAAAAAAAAABAQEBAQEBAQEBAQEBAQEBAQEAAAAAAAAAAAAAAAAAAAEBAQEBAQEBAQEBAQEBAQEBAQAAAAAAAAAAAAAAAAAAAQEBAQEBAQEBAQEBAAAAAAAAAAAAAAAAAAAAAAAAAAABAQEBAQEBAQEBAQEAAAAAAAAAAAAAAAAAAAAAAAAAAAEBAQEBAQEBAQEBAQAAAAAAAAAAAAAAAAAAAQEBAQEBAQEBAQEBAQEBAQEBAAAAAAAAAAAAAAAAAAABAQEBAQEBAQEBAQEBAQEBAQEAAAAAAAAAAAAAAAAAAAEBAQEBAQEBAQEBAQEBAQEBAQAAAAAAAAAAAAAAAAAAAQEBAQEBAQEBAQEBAQEBAQEBAAAAAAAAAAAAAAAAAAABAQEBAQEBAQEBAQEBAQEBAQEAAAAAAAAAAAAAAAAAAAEBAQEBAQEBAQEBAQ==" + }, + "palette" : { + "originalArgb8888" : [ -265674 ], + "convertedRgb565" : [ -122 ] } }, "diagnostics" : [ ] @@ -474,14 +474,14 @@ "last_modified" : 1774359772436, "fingerprint" : "eeb7cc665386299403b7be1c272375d5077f3647c587f8033aa8c9275f840562", "metadata" : { - "palette" : { - "originalArgb8888" : [ -265674 ], - "convertedRgb565" : [ -122 ] - }, "tile" : { "width" : 32, "height" : 32, "paletteIndices" : "AQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAAAAAAAAAAABAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEAAAAAAAAAAAEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQAAAAAAAAAAAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAAAAAAAAAAABAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEAAAAAAAAAAAEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQAAAAAAAAAAAQEBAQEBAQEBAQEBAAAAAAAAAAAAAAAAAAAAAAAAAAABAQEBAQEBAQEBAQEAAAAAAAAAAAAAAAAAAAAAAAAAAAEBAQEBAQEBAQEBAQAAAAAAAAAAAAAAAAAAAAAAAAAAAQEBAQEBAQEBAQEBAAAAAAAAAAAAAAAAAAAAAAAAAAABAQEBAQEBAQEBAQEAAAAAAAAAAAAAAAAAAAAAAAAAAAEBAQEBAQEBAQEBAQAAAAAAAAAAAAAAAAAAAAAAAAAAAQEBAQEBAQEBAQEBAAAAAAAAAAAAAAAAAAAAAAAAAAABAQEBAQEBAQEBAQEAAAAAAAAAAAAAAAAAAAAAAAAAAAEBAQEBAQEBAQEBAQAAAAAAAAAAAAAAAAAAAQEBAQEBAQEBAQEBAQEBAQEBAAAAAAAAAAAAAAAAAAABAQEBAQEBAQEBAQEBAQEBAQEAAAAAAAAAAAAAAAAAAAEBAQEBAQEBAQEBAQEBAQEBAQAAAAAAAAAAAAAAAAAAAQEBAQEBAQEBAQEBAAAAAAAAAAAAAAAAAAAAAAAAAAABAQEBAQEBAQEBAQEAAAAAAAAAAAAAAAAAAAAAAAAAAAEBAQEBAQEBAQEBAQAAAAAAAAAAAAAAAAAAAQEBAQEBAQEBAQEBAQEBAQEBAAAAAAAAAAAAAAAAAAABAQEBAQEBAQEBAQEBAQEBAQEAAAAAAAAAAAAAAAAAAAEBAQEBAQEBAQEBAQEBAQEBAQAAAAAAAAAAAAAAAAAAAQEBAQEBAQEBAQEBAQEBAQEBAAAAAAAAAAAAAAAAAAABAQEBAQEBAQEBAQEBAQEBAQEAAAAAAAAAAAAAAAAAAAEBAQEBAQEBAQEBAQ==" + }, + "palette" : { + "originalArgb8888" : [ -265674 ], + "convertedRgb565" : [ -122 ] } }, "diagnostics" : [ ] @@ -492,14 +492,14 @@ "last_modified" : 1774359772437, "fingerprint" : "eeb7cc665386299403b7be1c272375d5077f3647c587f8033aa8c9275f840562", "metadata" : { - "palette" : { - "originalArgb8888" : [ -265674 ], - "convertedRgb565" : [ -122 ] - }, "tile" : { "width" : 32, "height" : 32, "paletteIndices" : "AQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAAAAAAAAAAABAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEAAAAAAAAAAAEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQAAAAAAAAAAAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAAAAAAAAAAABAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEAAAAAAAAAAAEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQAAAAAAAAAAAQEBAQEBAQEBAQEBAAAAAAAAAAAAAAAAAAAAAAAAAAABAQEBAQEBAQEBAQEAAAAAAAAAAAAAAAAAAAAAAAAAAAEBAQEBAQEBAQEBAQAAAAAAAAAAAAAAAAAAAAAAAAAAAQEBAQEBAQEBAQEBAAAAAAAAAAAAAAAAAAAAAAAAAAABAQEBAQEBAQEBAQEAAAAAAAAAAAAAAAAAAAAAAAAAAAEBAQEBAQEBAQEBAQAAAAAAAAAAAAAAAAAAAAAAAAAAAQEBAQEBAQEBAQEBAAAAAAAAAAAAAAAAAAAAAAAAAAABAQEBAQEBAQEBAQEAAAAAAAAAAAAAAAAAAAAAAAAAAAEBAQEBAQEBAQEBAQAAAAAAAAAAAAAAAAAAAQEBAQEBAQEBAQEBAQEBAQEBAAAAAAAAAAAAAAAAAAABAQEBAQEBAQEBAQEBAQEBAQEAAAAAAAAAAAAAAAAAAAEBAQEBAQEBAQEBAQEBAQEBAQAAAAAAAAAAAAAAAAAAAQEBAQEBAQEBAQEBAAAAAAAAAAAAAAAAAAAAAAAAAAABAQEBAQEBAQEBAQEAAAAAAAAAAAAAAAAAAAAAAAAAAAEBAQEBAQEBAQEBAQAAAAAAAAAAAAAAAAAAAQEBAQEBAQEBAQEBAQEBAQEBAAAAAAAAAAAAAAAAAAABAQEBAQEBAQEBAQEBAQEBAQEAAAAAAAAAAAAAAAAAAAEBAQEBAQEBAQEBAQEBAQEBAQAAAAAAAAAAAAAAAAAAAQEBAQEBAQEBAQEBAQEBAQEBAAAAAAAAAAAAAAAAAAABAQEBAQEBAQEBAQEBAQEBAQEAAAAAAAAAAAAAAAAAAAEBAQEBAQEBAQEBAQ==" + }, + "palette" : { + "originalArgb8888" : [ -265674 ], + "convertedRgb565" : [ -122 ] } }, "diagnostics" : [ ] @@ -510,14 +510,14 @@ "last_modified" : 1774359772438, "fingerprint" : "eeb7cc665386299403b7be1c272375d5077f3647c587f8033aa8c9275f840562", "metadata" : { - "palette" : { - "originalArgb8888" : [ -265674 ], - "convertedRgb565" : [ -122 ] - }, "tile" : { "width" : 32, "height" : 32, "paletteIndices" : "AQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAAAAAAAAAAABAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEAAAAAAAAAAAEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQAAAAAAAAAAAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAAAAAAAAAAABAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEAAAAAAAAAAAEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQAAAAAAAAAAAQEBAQEBAQEBAQEBAAAAAAAAAAAAAAAAAAAAAAAAAAABAQEBAQEBAQEBAQEAAAAAAAAAAAAAAAAAAAAAAAAAAAEBAQEBAQEBAQEBAQAAAAAAAAAAAAAAAAAAAAAAAAAAAQEBAQEBAQEBAQEBAAAAAAAAAAAAAAAAAAAAAAAAAAABAQEBAQEBAQEBAQEAAAAAAAAAAAAAAAAAAAAAAAAAAAEBAQEBAQEBAQEBAQAAAAAAAAAAAAAAAAAAAAAAAAAAAQEBAQEBAQEBAQEBAAAAAAAAAAAAAAAAAAAAAAAAAAABAQEBAQEBAQEBAQEAAAAAAAAAAAAAAAAAAAAAAAAAAAEBAQEBAQEBAQEBAQAAAAAAAAAAAAAAAAAAAQEBAQEBAQEBAQEBAQEBAQEBAAAAAAAAAAAAAAAAAAABAQEBAQEBAQEBAQEBAQEBAQEAAAAAAAAAAAAAAAAAAAEBAQEBAQEBAQEBAQEBAQEBAQAAAAAAAAAAAAAAAAAAAQEBAQEBAQEBAQEBAAAAAAAAAAAAAAAAAAAAAAAAAAABAQEBAQEBAQEBAQEAAAAAAAAAAAAAAAAAAAAAAAAAAAEBAQEBAQEBAQEBAQAAAAAAAAAAAAAAAAAAAQEBAQEBAQEBAQEBAQEBAQEBAAAAAAAAAAAAAAAAAAABAQEBAQEBAQEBAQEBAQEBAQEAAAAAAAAAAAAAAAAAAAEBAQEBAQEBAQEBAQEBAQEBAQAAAAAAAAAAAAAAAAAAAQEBAQEBAQEBAQEBAQEBAQEBAAAAAAAAAAAAAAAAAAABAQEBAQEBAQEBAQEBAQEBAQEAAAAAAAAAAAAAAAAAAAEBAQEBAQEBAQEBAQ==" + }, + "palette" : { + "originalArgb8888" : [ -265674 ], + "convertedRgb565" : [ -122 ] } }, "diagnostics" : [ ] @@ -528,14 +528,14 @@ "last_modified" : 1774359772439, "fingerprint" : "eeb7cc665386299403b7be1c272375d5077f3647c587f8033aa8c9275f840562", "metadata" : { - "palette" : { - "originalArgb8888" : [ -265674 ], - "convertedRgb565" : [ -122 ] - }, "tile" : { "width" : 32, "height" : 32, "paletteIndices" : "AQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAAAAAAAAAAABAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEAAAAAAAAAAAEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQAAAAAAAAAAAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAAAAAAAAAAABAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEAAAAAAAAAAAEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQAAAAAAAAAAAQEBAQEBAQEBAQEBAAAAAAAAAAAAAAAAAAAAAAAAAAABAQEBAQEBAQEBAQEAAAAAAAAAAAAAAAAAAAAAAAAAAAEBAQEBAQEBAQEBAQAAAAAAAAAAAAAAAAAAAAAAAAAAAQEBAQEBAQEBAQEBAAAAAAAAAAAAAAAAAAAAAAAAAAABAQEBAQEBAQEBAQEAAAAAAAAAAAAAAAAAAAAAAAAAAAEBAQEBAQEBAQEBAQAAAAAAAAAAAAAAAAAAAAAAAAAAAQEBAQEBAQEBAQEBAAAAAAAAAAAAAAAAAAAAAAAAAAABAQEBAQEBAQEBAQEAAAAAAAAAAAAAAAAAAAAAAAAAAAEBAQEBAQEBAQEBAQAAAAAAAAAAAAAAAAAAAQEBAQEBAQEBAQEBAQEBAQEBAAAAAAAAAAAAAAAAAAABAQEBAQEBAQEBAQEBAQEBAQEAAAAAAAAAAAAAAAAAAAEBAQEBAQEBAQEBAQEBAQEBAQAAAAAAAAAAAAAAAAAAAQEBAQEBAQEBAQEBAAAAAAAAAAAAAAAAAAAAAAAAAAABAQEBAQEBAQEBAQEAAAAAAAAAAAAAAAAAAAAAAAAAAAEBAQEBAQEBAQEBAQAAAAAAAAAAAAAAAAAAAQEBAQEBAQEBAQEBAQEBAQEBAAAAAAAAAAAAAAAAAAABAQEBAQEBAQEBAQEBAQEBAQEAAAAAAAAAAAAAAAAAAAEBAQEBAQEBAQEBAQEBAQEBAQAAAAAAAAAAAAAAAAAAAQEBAQEBAQEBAQEBAQEBAQEBAAAAAAAAAAAAAAAAAAABAQEBAQEBAQEBAQEBAQEBAQEAAAAAAAAAAAAAAAAAAAEBAQEBAQEBAQEBAQ==" + }, + "palette" : { + "originalArgb8888" : [ -265674 ], + "convertedRgb565" : [ -122 ] } }, "diagnostics" : [ ] @@ -546,14 +546,14 @@ "last_modified" : 1774359772441, "fingerprint" : "eeb7cc665386299403b7be1c272375d5077f3647c587f8033aa8c9275f840562", "metadata" : { - "palette" : { - "originalArgb8888" : [ -265674 ], - "convertedRgb565" : [ -122 ] - }, "tile" : { "width" : 32, "height" : 32, "paletteIndices" : "AQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAAAAAAAAAAABAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEAAAAAAAAAAAEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQAAAAAAAAAAAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAAAAAAAAAAABAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEAAAAAAAAAAAEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQAAAAAAAAAAAQEBAQEBAQEBAQEBAAAAAAAAAAAAAAAAAAAAAAAAAAABAQEBAQEBAQEBAQEAAAAAAAAAAAAAAAAAAAAAAAAAAAEBAQEBAQEBAQEBAQAAAAAAAAAAAAAAAAAAAAAAAAAAAQEBAQEBAQEBAQEBAAAAAAAAAAAAAAAAAAAAAAAAAAABAQEBAQEBAQEBAQEAAAAAAAAAAAAAAAAAAAAAAAAAAAEBAQEBAQEBAQEBAQAAAAAAAAAAAAAAAAAAAAAAAAAAAQEBAQEBAQEBAQEBAAAAAAAAAAAAAAAAAAAAAAAAAAABAQEBAQEBAQEBAQEAAAAAAAAAAAAAAAAAAAAAAAAAAAEBAQEBAQEBAQEBAQAAAAAAAAAAAAAAAAAAAQEBAQEBAQEBAQEBAQEBAQEBAAAAAAAAAAAAAAAAAAABAQEBAQEBAQEBAQEBAQEBAQEAAAAAAAAAAAAAAAAAAAEBAQEBAQEBAQEBAQEBAQEBAQAAAAAAAAAAAAAAAAAAAQEBAQEBAQEBAQEBAAAAAAAAAAAAAAAAAAAAAAAAAAABAQEBAQEBAQEBAQEAAAAAAAAAAAAAAAAAAAAAAAAAAAEBAQEBAQEBAQEBAQAAAAAAAAAAAAAAAAAAAQEBAQEBAQEBAQEBAQEBAQEBAAAAAAAAAAAAAAAAAAABAQEBAQEBAQEBAQEBAQEBAQEAAAAAAAAAAAAAAAAAAAEBAQEBAQEBAQEBAQEBAQEBAQAAAAAAAAAAAAAAAAAAAQEBAQEBAQEBAQEBAQEBAQEBAAAAAAAAAAAAAAAAAAABAQEBAQEBAQEBAQEBAQEBAQEAAAAAAAAAAAAAAAAAAAEBAQEBAQEBAQEBAQ==" + }, + "palette" : { + "originalArgb8888" : [ -265674 ], + "convertedRgb565" : [ -122 ] } }, "diagnostics" : [ ] @@ -564,14 +564,14 @@ "last_modified" : 1774359772442, "fingerprint" : "eeb7cc665386299403b7be1c272375d5077f3647c587f8033aa8c9275f840562", "metadata" : { - "palette" : { - "originalArgb8888" : [ -265674 ], - "convertedRgb565" : [ -122 ] - }, "tile" : { "width" : 32, "height" : 32, "paletteIndices" : "AQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAAAAAAAAAAABAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEAAAAAAAAAAAEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQAAAAAAAAAAAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAAAAAAAAAAABAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEAAAAAAAAAAAEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQAAAAAAAAAAAQEBAQEBAQEBAQEBAAAAAAAAAAAAAAAAAAAAAAAAAAABAQEBAQEBAQEBAQEAAAAAAAAAAAAAAAAAAAAAAAAAAAEBAQEBAQEBAQEBAQAAAAAAAAAAAAAAAAAAAAAAAAAAAQEBAQEBAQEBAQEBAAAAAAAAAAAAAAAAAAAAAAAAAAABAQEBAQEBAQEBAQEAAAAAAAAAAAAAAAAAAAAAAAAAAAEBAQEBAQEBAQEBAQAAAAAAAAAAAAAAAAAAAAAAAAAAAQEBAQEBAQEBAQEBAAAAAAAAAAAAAAAAAAAAAAAAAAABAQEBAQEBAQEBAQEAAAAAAAAAAAAAAAAAAAAAAAAAAAEBAQEBAQEBAQEBAQAAAAAAAAAAAAAAAAAAAQEBAQEBAQEBAQEBAQEBAQEBAAAAAAAAAAAAAAAAAAABAQEBAQEBAQEBAQEBAQEBAQEAAAAAAAAAAAAAAAAAAAEBAQEBAQEBAQEBAQEBAQEBAQAAAAAAAAAAAAAAAAAAAQEBAQEBAQEBAQEBAAAAAAAAAAAAAAAAAAAAAAAAAAABAQEBAQEBAQEBAQEAAAAAAAAAAAAAAAAAAAAAAAAAAAEBAQEBAQEBAQEBAQAAAAAAAAAAAAAAAAAAAQEBAQEBAQEBAQEBAQEBAQEBAAAAAAAAAAAAAAAAAAABAQEBAQEBAQEBAQEBAQEBAQEAAAAAAAAAAAAAAAAAAAEBAQEBAQEBAQEBAQEBAQEBAQAAAAAAAAAAAAAAAAAAAQEBAQEBAQEBAQEBAQEBAQEBAAAAAAAAAAAAAAAAAAABAQEBAQEBAQEBAQEBAQEBAQEAAAAAAAAAAAAAAAAAAAEBAQEBAQEBAQEBAQ==" + }, + "palette" : { + "originalArgb8888" : [ -265674 ], + "convertedRgb565" : [ -122 ] } }, "diagnostics" : [ ] @@ -582,14 +582,14 @@ "last_modified" : 1774359772443, "fingerprint" : "eeb7cc665386299403b7be1c272375d5077f3647c587f8033aa8c9275f840562", "metadata" : { - "palette" : { - "originalArgb8888" : [ -265674 ], - "convertedRgb565" : [ -122 ] - }, "tile" : { "width" : 32, "height" : 32, "paletteIndices" : "AQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAAAAAAAAAAABAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEAAAAAAAAAAAEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQAAAAAAAAAAAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAAAAAAAAAAABAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEAAAAAAAAAAAEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQAAAAAAAAAAAQEBAQEBAQEBAQEBAAAAAAAAAAAAAAAAAAAAAAAAAAABAQEBAQEBAQEBAQEAAAAAAAAAAAAAAAAAAAAAAAAAAAEBAQEBAQEBAQEBAQAAAAAAAAAAAAAAAAAAAAAAAAAAAQEBAQEBAQEBAQEBAAAAAAAAAAAAAAAAAAAAAAAAAAABAQEBAQEBAQEBAQEAAAAAAAAAAAAAAAAAAAAAAAAAAAEBAQEBAQEBAQEBAQAAAAAAAAAAAAAAAAAAAAAAAAAAAQEBAQEBAQEBAQEBAAAAAAAAAAAAAAAAAAAAAAAAAAABAQEBAQEBAQEBAQEAAAAAAAAAAAAAAAAAAAAAAAAAAAEBAQEBAQEBAQEBAQAAAAAAAAAAAAAAAAAAAQEBAQEBAQEBAQEBAQEBAQEBAAAAAAAAAAAAAAAAAAABAQEBAQEBAQEBAQEBAQEBAQEAAAAAAAAAAAAAAAAAAAEBAQEBAQEBAQEBAQEBAQEBAQAAAAAAAAAAAAAAAAAAAQEBAQEBAQEBAQEBAAAAAAAAAAAAAAAAAAAAAAAAAAABAQEBAQEBAQEBAQEAAAAAAAAAAAAAAAAAAAAAAAAAAAEBAQEBAQEBAQEBAQAAAAAAAAAAAAAAAAAAAQEBAQEBAQEBAQEBAQEBAQEBAAAAAAAAAAAAAAAAAAABAQEBAQEBAQEBAQEBAQEBAQEAAAAAAAAAAAAAAAAAAAEBAQEBAQEBAQEBAQEBAQEBAQAAAAAAAAAAAAAAAAAAAQEBAQEBAQEBAQEBAQEBAQEBAAAAAAAAAAAAAAAAAAABAQEBAQEBAQEBAQEBAQEBAQEAAAAAAAAAAAAAAAAAAAEBAQEBAQEBAQEBAQ==" + }, + "palette" : { + "originalArgb8888" : [ -265674 ], + "convertedRgb565" : [ -122 ] } }, "diagnostics" : [ ] @@ -600,14 +600,14 @@ "last_modified" : 1774359772444, "fingerprint" : "eeb7cc665386299403b7be1c272375d5077f3647c587f8033aa8c9275f840562", "metadata" : { - "palette" : { - "originalArgb8888" : [ -265674 ], - "convertedRgb565" : [ -122 ] - }, "tile" : { "width" : 32, "height" : 32, "paletteIndices" : "AQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAAAAAAAAAAABAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEAAAAAAAAAAAEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQAAAAAAAAAAAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAAAAAAAAAAABAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEAAAAAAAAAAAEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQAAAAAAAAAAAQEBAQEBAQEBAQEBAAAAAAAAAAAAAAAAAAAAAAAAAAABAQEBAQEBAQEBAQEAAAAAAAAAAAAAAAAAAAAAAAAAAAEBAQEBAQEBAQEBAQAAAAAAAAAAAAAAAAAAAAAAAAAAAQEBAQEBAQEBAQEBAAAAAAAAAAAAAAAAAAAAAAAAAAABAQEBAQEBAQEBAQEAAAAAAAAAAAAAAAAAAAAAAAAAAAEBAQEBAQEBAQEBAQAAAAAAAAAAAAAAAAAAAAAAAAAAAQEBAQEBAQEBAQEBAAAAAAAAAAAAAAAAAAAAAAAAAAABAQEBAQEBAQEBAQEAAAAAAAAAAAAAAAAAAAAAAAAAAAEBAQEBAQEBAQEBAQAAAAAAAAAAAAAAAAAAAQEBAQEBAQEBAQEBAQEBAQEBAAAAAAAAAAAAAAAAAAABAQEBAQEBAQEBAQEBAQEBAQEAAAAAAAAAAAAAAAAAAAEBAQEBAQEBAQEBAQEBAQEBAQAAAAAAAAAAAAAAAAAAAQEBAQEBAQEBAQEBAAAAAAAAAAAAAAAAAAAAAAAAAAABAQEBAQEBAQEBAQEAAAAAAAAAAAAAAAAAAAAAAAAAAAEBAQEBAQEBAQEBAQAAAAAAAAAAAAAAAAAAAQEBAQEBAQEBAQEBAQEBAQEBAAAAAAAAAAAAAAAAAAABAQEBAQEBAQEBAQEBAQEBAQEAAAAAAAAAAAAAAAAAAAEBAQEBAQEBAQEBAQEBAQEBAQAAAAAAAAAAAAAAAAAAAQEBAQEBAQEBAQEBAQEBAQEBAAAAAAAAAAAAAAAAAAABAQEBAQEBAQEBAQEBAQEBAQEAAAAAAAAAAAAAAAAAAAEBAQEBAQEBAQEBAQ==" + }, + "palette" : { + "originalArgb8888" : [ -265674 ], + "convertedRgb565" : [ -122 ] } }, "diagnostics" : [ ] @@ -618,14 +618,14 @@ "last_modified" : 1774359772445, "fingerprint" : "eeb7cc665386299403b7be1c272375d5077f3647c587f8033aa8c9275f840562", "metadata" : { - "palette" : { - "originalArgb8888" : [ -265674 ], - "convertedRgb565" : [ -122 ] - }, "tile" : { "width" : 32, "height" : 32, "paletteIndices" : "AQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAAAAAAAAAAABAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEAAAAAAAAAAAEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQAAAAAAAAAAAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAAAAAAAAAAABAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEAAAAAAAAAAAEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQAAAAAAAAAAAQEBAQEBAQEBAQEBAAAAAAAAAAAAAAAAAAAAAAAAAAABAQEBAQEBAQEBAQEAAAAAAAAAAAAAAAAAAAAAAAAAAAEBAQEBAQEBAQEBAQAAAAAAAAAAAAAAAAAAAAAAAAAAAQEBAQEBAQEBAQEBAAAAAAAAAAAAAAAAAAAAAAAAAAABAQEBAQEBAQEBAQEAAAAAAAAAAAAAAAAAAAAAAAAAAAEBAQEBAQEBAQEBAQAAAAAAAAAAAAAAAAAAAAAAAAAAAQEBAQEBAQEBAQEBAAAAAAAAAAAAAAAAAAAAAAAAAAABAQEBAQEBAQEBAQEAAAAAAAAAAAAAAAAAAAAAAAAAAAEBAQEBAQEBAQEBAQAAAAAAAAAAAAAAAAAAAQEBAQEBAQEBAQEBAQEBAQEBAAAAAAAAAAAAAAAAAAABAQEBAQEBAQEBAQEBAQEBAQEAAAAAAAAAAAAAAAAAAAEBAQEBAQEBAQEBAQEBAQEBAQAAAAAAAAAAAAAAAAAAAQEBAQEBAQEBAQEBAAAAAAAAAAAAAAAAAAAAAAAAAAABAQEBAQEBAQEBAQEAAAAAAAAAAAAAAAAAAAAAAAAAAAEBAQEBAQEBAQEBAQAAAAAAAAAAAAAAAAAAAQEBAQEBAQEBAQEBAQEBAQEBAAAAAAAAAAAAAAAAAAABAQEBAQEBAQEBAQEBAQEBAQEAAAAAAAAAAAAAAAAAAAEBAQEBAQEBAQEBAQEBAQEBAQAAAAAAAAAAAAAAAAAAAQEBAQEBAQEBAQEBAQEBAQEBAAAAAAAAAAAAAAAAAAABAQEBAQEBAQEBAQEBAQEBAQEAAAAAAAAAAAAAAAAAAAEBAQEBAQEBAQEBAQ==" + }, + "palette" : { + "originalArgb8888" : [ -265674 ], + "convertedRgb565" : [ -122 ] } }, "diagnostics" : [ ] @@ -636,14 +636,14 @@ "last_modified" : 1774359772448, "fingerprint" : "eeb7cc665386299403b7be1c272375d5077f3647c587f8033aa8c9275f840562", "metadata" : { - "palette" : { - "originalArgb8888" : [ -265674 ], - "convertedRgb565" : [ -122 ] - }, "tile" : { "width" : 32, "height" : 32, "paletteIndices" : "AQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAAAAAAAAAAABAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEAAAAAAAAAAAEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQAAAAAAAAAAAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAAAAAAAAAAABAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEAAAAAAAAAAAEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQAAAAAAAAAAAQEBAQEBAQEBAQEBAAAAAAAAAAAAAAAAAAAAAAAAAAABAQEBAQEBAQEBAQEAAAAAAAAAAAAAAAAAAAAAAAAAAAEBAQEBAQEBAQEBAQAAAAAAAAAAAAAAAAAAAAAAAAAAAQEBAQEBAQEBAQEBAAAAAAAAAAAAAAAAAAAAAAAAAAABAQEBAQEBAQEBAQEAAAAAAAAAAAAAAAAAAAAAAAAAAAEBAQEBAQEBAQEBAQAAAAAAAAAAAAAAAAAAAAAAAAAAAQEBAQEBAQEBAQEBAAAAAAAAAAAAAAAAAAAAAAAAAAABAQEBAQEBAQEBAQEAAAAAAAAAAAAAAAAAAAAAAAAAAAEBAQEBAQEBAQEBAQAAAAAAAAAAAAAAAAAAAQEBAQEBAQEBAQEBAQEBAQEBAAAAAAAAAAAAAAAAAAABAQEBAQEBAQEBAQEBAQEBAQEAAAAAAAAAAAAAAAAAAAEBAQEBAQEBAQEBAQEBAQEBAQAAAAAAAAAAAAAAAAAAAQEBAQEBAQEBAQEBAAAAAAAAAAAAAAAAAAAAAAAAAAABAQEBAQEBAQEBAQEAAAAAAAAAAAAAAAAAAAAAAAAAAAEBAQEBAQEBAQEBAQAAAAAAAAAAAAAAAAAAAQEBAQEBAQEBAQEBAQEBAQEBAAAAAAAAAAAAAAAAAAABAQEBAQEBAQEBAQEBAQEBAQEAAAAAAAAAAAAAAAAAAAEBAQEBAQEBAQEBAQEBAQEBAQAAAAAAAAAAAAAAAAAAAQEBAQEBAQEBAQEBAQEBAQEBAAAAAAAAAAAAAAAAAAABAQEBAQEBAQEBAQEBAQEBAQEAAAAAAAAAAAAAAAAAAAEBAQEBAQEBAQEBAQ==" + }, + "palette" : { + "originalArgb8888" : [ -265674 ], + "convertedRgb565" : [ -122 ] } }, "diagnostics" : [ ] @@ -654,14 +654,14 @@ "last_modified" : 1774359772449, "fingerprint" : "eeb7cc665386299403b7be1c272375d5077f3647c587f8033aa8c9275f840562", "metadata" : { - "palette" : { - "originalArgb8888" : [ -265674 ], - "convertedRgb565" : [ -122 ] - }, "tile" : { "width" : 32, "height" : 32, "paletteIndices" : "AQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAAAAAAAAAAABAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEAAAAAAAAAAAEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQAAAAAAAAAAAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAAAAAAAAAAABAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEAAAAAAAAAAAEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQAAAAAAAAAAAQEBAQEBAQEBAQEBAAAAAAAAAAAAAAAAAAAAAAAAAAABAQEBAQEBAQEBAQEAAAAAAAAAAAAAAAAAAAAAAAAAAAEBAQEBAQEBAQEBAQAAAAAAAAAAAAAAAAAAAAAAAAAAAQEBAQEBAQEBAQEBAAAAAAAAAAAAAAAAAAAAAAAAAAABAQEBAQEBAQEBAQEAAAAAAAAAAAAAAAAAAAAAAAAAAAEBAQEBAQEBAQEBAQAAAAAAAAAAAAAAAAAAAAAAAAAAAQEBAQEBAQEBAQEBAAAAAAAAAAAAAAAAAAAAAAAAAAABAQEBAQEBAQEBAQEAAAAAAAAAAAAAAAAAAAAAAAAAAAEBAQEBAQEBAQEBAQAAAAAAAAAAAAAAAAAAAQEBAQEBAQEBAQEBAQEBAQEBAAAAAAAAAAAAAAAAAAABAQEBAQEBAQEBAQEBAQEBAQEAAAAAAAAAAAAAAAAAAAEBAQEBAQEBAQEBAQEBAQEBAQAAAAAAAAAAAAAAAAAAAQEBAQEBAQEBAQEBAAAAAAAAAAAAAAAAAAAAAAAAAAABAQEBAQEBAQEBAQEAAAAAAAAAAAAAAAAAAAAAAAAAAAEBAQEBAQEBAQEBAQAAAAAAAAAAAAAAAAAAAQEBAQEBAQEBAQEBAQEBAQEBAAAAAAAAAAAAAAAAAAABAQEBAQEBAQEBAQEBAQEBAQEAAAAAAAAAAAAAAAAAAAEBAQEBAQEBAQEBAQEBAQEBAQAAAAAAAAAAAAAAAAAAAQEBAQEBAQEBAQEBAQEBAQEBAAAAAAAAAAAAAAAAAAABAQEBAQEBAQEBAQEBAQEBAQEAAAAAAAAAAAAAAAAAAAEBAQEBAQEBAQEBAQ==" + }, + "palette" : { + "originalArgb8888" : [ -265674 ], + "convertedRgb565" : [ -122 ] } }, "diagnostics" : [ ] @@ -672,14 +672,14 @@ "last_modified" : 1774359772450, "fingerprint" : "eeb7cc665386299403b7be1c272375d5077f3647c587f8033aa8c9275f840562", "metadata" : { - "palette" : { - "originalArgb8888" : [ -265674 ], - "convertedRgb565" : [ -122 ] - }, "tile" : { "width" : 32, "height" : 32, "paletteIndices" : "AQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAAAAAAAAAAABAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEAAAAAAAAAAAEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQAAAAAAAAAAAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAAAAAAAAAAABAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEAAAAAAAAAAAEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQAAAAAAAAAAAQEBAQEBAQEBAQEBAAAAAAAAAAAAAAAAAAAAAAAAAAABAQEBAQEBAQEBAQEAAAAAAAAAAAAAAAAAAAAAAAAAAAEBAQEBAQEBAQEBAQAAAAAAAAAAAAAAAAAAAAAAAAAAAQEBAQEBAQEBAQEBAAAAAAAAAAAAAAAAAAAAAAAAAAABAQEBAQEBAQEBAQEAAAAAAAAAAAAAAAAAAAAAAAAAAAEBAQEBAQEBAQEBAQAAAAAAAAAAAAAAAAAAAAAAAAAAAQEBAQEBAQEBAQEBAAAAAAAAAAAAAAAAAAAAAAAAAAABAQEBAQEBAQEBAQEAAAAAAAAAAAAAAAAAAAAAAAAAAAEBAQEBAQEBAQEBAQAAAAAAAAAAAAAAAAAAAQEBAQEBAQEBAQEBAQEBAQEBAAAAAAAAAAAAAAAAAAABAQEBAQEBAQEBAQEBAQEBAQEAAAAAAAAAAAAAAAAAAAEBAQEBAQEBAQEBAQEBAQEBAQAAAAAAAAAAAAAAAAAAAQEBAQEBAQEBAQEBAAAAAAAAAAAAAAAAAAAAAAAAAAABAQEBAQEBAQEBAQEAAAAAAAAAAAAAAAAAAAAAAAAAAAEBAQEBAQEBAQEBAQAAAAAAAAAAAAAAAAAAAQEBAQEBAQEBAQEBAQEBAQEBAAAAAAAAAAAAAAAAAAABAQEBAQEBAQEBAQEBAQEBAQEAAAAAAAAAAAAAAAAAAAEBAQEBAQEBAQEBAQEBAQEBAQAAAAAAAAAAAAAAAAAAAQEBAQEBAQEBAQEBAQEBAQEBAAAAAAAAAAAAAAAAAAABAQEBAQEBAQEBAQEBAQEBAQEAAAAAAAAAAAAAAAAAAAEBAQEBAQEBAQEBAQ==" + }, + "palette" : { + "originalArgb8888" : [ -265674 ], + "convertedRgb565" : [ -122 ] } }, "diagnostics" : [ ] @@ -690,14 +690,14 @@ "last_modified" : 1774359772452, "fingerprint" : "eeb7cc665386299403b7be1c272375d5077f3647c587f8033aa8c9275f840562", "metadata" : { - "palette" : { - "originalArgb8888" : [ -265674 ], - "convertedRgb565" : [ -122 ] - }, "tile" : { "width" : 32, "height" : 32, "paletteIndices" : "AQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAAAAAAAAAAABAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEAAAAAAAAAAAEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQAAAAAAAAAAAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAAAAAAAAAAABAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEAAAAAAAAAAAEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQAAAAAAAAAAAQEBAQEBAQEBAQEBAAAAAAAAAAAAAAAAAAAAAAAAAAABAQEBAQEBAQEBAQEAAAAAAAAAAAAAAAAAAAAAAAAAAAEBAQEBAQEBAQEBAQAAAAAAAAAAAAAAAAAAAAAAAAAAAQEBAQEBAQEBAQEBAAAAAAAAAAAAAAAAAAAAAAAAAAABAQEBAQEBAQEBAQEAAAAAAAAAAAAAAAAAAAAAAAAAAAEBAQEBAQEBAQEBAQAAAAAAAAAAAAAAAAAAAAAAAAAAAQEBAQEBAQEBAQEBAAAAAAAAAAAAAAAAAAAAAAAAAAABAQEBAQEBAQEBAQEAAAAAAAAAAAAAAAAAAAAAAAAAAAEBAQEBAQEBAQEBAQAAAAAAAAAAAAAAAAAAAQEBAQEBAQEBAQEBAQEBAQEBAAAAAAAAAAAAAAAAAAABAQEBAQEBAQEBAQEBAQEBAQEAAAAAAAAAAAAAAAAAAAEBAQEBAQEBAQEBAQEBAQEBAQAAAAAAAAAAAAAAAAAAAQEBAQEBAQEBAQEBAAAAAAAAAAAAAAAAAAAAAAAAAAABAQEBAQEBAQEBAQEAAAAAAAAAAAAAAAAAAAAAAAAAAAEBAQEBAQEBAQEBAQAAAAAAAAAAAAAAAAAAAQEBAQEBAQEBAQEBAQEBAQEBAAAAAAAAAAAAAAAAAAABAQEBAQEBAQEBAQEBAQEBAQEAAAAAAAAAAAAAAAAAAAEBAQEBAQEBAQEBAQEBAQEBAQAAAAAAAAAAAAAAAAAAAQEBAQEBAQEBAQEBAQEBAQEBAAAAAAAAAAAAAAAAAAABAQEBAQEBAQEBAQEBAQEBAQEAAAAAAAAAAAAAAAAAAAEBAQEBAQEBAQEBAQ==" + }, + "palette" : { + "originalArgb8888" : [ -265674 ], + "convertedRgb565" : [ -122 ] } }, "diagnostics" : [ ] @@ -708,14 +708,14 @@ "last_modified" : 1774359772453, "fingerprint" : "eeb7cc665386299403b7be1c272375d5077f3647c587f8033aa8c9275f840562", "metadata" : { - "palette" : { - "originalArgb8888" : [ -265674 ], - "convertedRgb565" : [ -122 ] - }, "tile" : { "width" : 32, "height" : 32, "paletteIndices" : "AQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAAAAAAAAAAABAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEAAAAAAAAAAAEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQAAAAAAAAAAAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAAAAAAAAAAABAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEAAAAAAAAAAAEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQAAAAAAAAAAAQEBAQEBAQEBAQEBAAAAAAAAAAAAAAAAAAAAAAAAAAABAQEBAQEBAQEBAQEAAAAAAAAAAAAAAAAAAAAAAAAAAAEBAQEBAQEBAQEBAQAAAAAAAAAAAAAAAAAAAAAAAAAAAQEBAQEBAQEBAQEBAAAAAAAAAAAAAAAAAAAAAAAAAAABAQEBAQEBAQEBAQEAAAAAAAAAAAAAAAAAAAAAAAAAAAEBAQEBAQEBAQEBAQAAAAAAAAAAAAAAAAAAAAAAAAAAAQEBAQEBAQEBAQEBAAAAAAAAAAAAAAAAAAAAAAAAAAABAQEBAQEBAQEBAQEAAAAAAAAAAAAAAAAAAAAAAAAAAAEBAQEBAQEBAQEBAQAAAAAAAAAAAAAAAAAAAQEBAQEBAQEBAQEBAQEBAQEBAAAAAAAAAAAAAAAAAAABAQEBAQEBAQEBAQEBAQEBAQEAAAAAAAAAAAAAAAAAAAEBAQEBAQEBAQEBAQEBAQEBAQAAAAAAAAAAAAAAAAAAAQEBAQEBAQEBAQEBAAAAAAAAAAAAAAAAAAAAAAAAAAABAQEBAQEBAQEBAQEAAAAAAAAAAAAAAAAAAAAAAAAAAAEBAQEBAQEBAQEBAQAAAAAAAAAAAAAAAAAAAQEBAQEBAQEBAQEBAQEBAQEBAAAAAAAAAAAAAAAAAAABAQEBAQEBAQEBAQEBAQEBAQEAAAAAAAAAAAAAAAAAAAEBAQEBAQEBAQEBAQEBAQEBAQAAAAAAAAAAAAAAAAAAAQEBAQEBAQEBAQEBAQEBAQEBAAAAAAAAAAAAAAAAAAABAQEBAQEBAQEBAQEBAQEBAQEAAAAAAAAAAAAAAAAAAAEBAQEBAQEBAQEBAQ==" + }, + "palette" : { + "originalArgb8888" : [ -265674 ], + "convertedRgb565" : [ -122 ] } }, "diagnostics" : [ ] @@ -726,14 +726,14 @@ "last_modified" : 1774359772454, "fingerprint" : "eeb7cc665386299403b7be1c272375d5077f3647c587f8033aa8c9275f840562", "metadata" : { - "palette" : { - "originalArgb8888" : [ -265674 ], - "convertedRgb565" : [ -122 ] - }, "tile" : { "width" : 32, "height" : 32, "paletteIndices" : "AQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAAAAAAAAAAABAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEAAAAAAAAAAAEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQAAAAAAAAAAAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAAAAAAAAAAABAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEAAAAAAAAAAAEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQAAAAAAAAAAAQEBAQEBAQEBAQEBAAAAAAAAAAAAAAAAAAAAAAAAAAABAQEBAQEBAQEBAQEAAAAAAAAAAAAAAAAAAAAAAAAAAAEBAQEBAQEBAQEBAQAAAAAAAAAAAAAAAAAAAAAAAAAAAQEBAQEBAQEBAQEBAAAAAAAAAAAAAAAAAAAAAAAAAAABAQEBAQEBAQEBAQEAAAAAAAAAAAAAAAAAAAAAAAAAAAEBAQEBAQEBAQEBAQAAAAAAAAAAAAAAAAAAAAAAAAAAAQEBAQEBAQEBAQEBAAAAAAAAAAAAAAAAAAAAAAAAAAABAQEBAQEBAQEBAQEAAAAAAAAAAAAAAAAAAAAAAAAAAAEBAQEBAQEBAQEBAQAAAAAAAAAAAAAAAAAAAQEBAQEBAQEBAQEBAQEBAQEBAAAAAAAAAAAAAAAAAAABAQEBAQEBAQEBAQEBAQEBAQEAAAAAAAAAAAAAAAAAAAEBAQEBAQEBAQEBAQEBAQEBAQAAAAAAAAAAAAAAAAAAAQEBAQEBAQEBAQEBAAAAAAAAAAAAAAAAAAAAAAAAAAABAQEBAQEBAQEBAQEAAAAAAAAAAAAAAAAAAAAAAAAAAAEBAQEBAQEBAQEBAQAAAAAAAAAAAAAAAAAAAQEBAQEBAQEBAQEBAQEBAQEBAAAAAAAAAAAAAAAAAAABAQEBAQEBAQEBAQEBAQEBAQEAAAAAAAAAAAAAAAAAAAEBAQEBAQEBAQEBAQEBAQEBAQAAAAAAAAAAAAAAAAAAAQEBAQEBAQEBAQEBAQEBAQEBAAAAAAAAAAAAAAAAAAABAQEBAQEBAQEBAQEBAQEBAQEAAAAAAAAAAAAAAAAAAAEBAQEBAQEBAQEBAQ==" + }, + "palette" : { + "originalArgb8888" : [ -265674 ], + "convertedRgb565" : [ -122 ] } }, "diagnostics" : [ ] @@ -744,14 +744,14 @@ "last_modified" : 1774359772455, "fingerprint" : "eeb7cc665386299403b7be1c272375d5077f3647c587f8033aa8c9275f840562", "metadata" : { - "palette" : { - "originalArgb8888" : [ -265674 ], - "convertedRgb565" : [ -122 ] - }, "tile" : { "width" : 32, "height" : 32, "paletteIndices" : "AQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAAAAAAAAAAABAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEAAAAAAAAAAAEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQAAAAAAAAAAAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAAAAAAAAAAABAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEAAAAAAAAAAAEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQAAAAAAAAAAAQEBAQEBAQEBAQEBAAAAAAAAAAAAAAAAAAAAAAAAAAABAQEBAQEBAQEBAQEAAAAAAAAAAAAAAAAAAAAAAAAAAAEBAQEBAQEBAQEBAQAAAAAAAAAAAAAAAAAAAAAAAAAAAQEBAQEBAQEBAQEBAAAAAAAAAAAAAAAAAAAAAAAAAAABAQEBAQEBAQEBAQEAAAAAAAAAAAAAAAAAAAAAAAAAAAEBAQEBAQEBAQEBAQAAAAAAAAAAAAAAAAAAAAAAAAAAAQEBAQEBAQEBAQEBAAAAAAAAAAAAAAAAAAAAAAAAAAABAQEBAQEBAQEBAQEAAAAAAAAAAAAAAAAAAAAAAAAAAAEBAQEBAQEBAQEBAQAAAAAAAAAAAAAAAAAAAQEBAQEBAQEBAQEBAQEBAQEBAAAAAAAAAAAAAAAAAAABAQEBAQEBAQEBAQEBAQEBAQEAAAAAAAAAAAAAAAAAAAEBAQEBAQEBAQEBAQEBAQEBAQAAAAAAAAAAAAAAAAAAAQEBAQEBAQEBAQEBAAAAAAAAAAAAAAAAAAAAAAAAAAABAQEBAQEBAQEBAQEAAAAAAAAAAAAAAAAAAAAAAAAAAAEBAQEBAQEBAQEBAQAAAAAAAAAAAAAAAAAAAQEBAQEBAQEBAQEBAQEBAQEBAAAAAAAAAAAAAAAAAAABAQEBAQEBAQEBAQEBAQEBAQEAAAAAAAAAAAAAAAAAAAEBAQEBAQEBAQEBAQEBAQEBAQAAAAAAAAAAAAAAAAAAAQEBAQEBAQEBAQEBAQEBAQEBAAAAAAAAAAAAAAAAAAABAQEBAQEBAQEBAQEBAQEBAQEAAAAAAAAAAAAAAAAAAAEBAQEBAQEBAQEBAQ==" + }, + "palette" : { + "originalArgb8888" : [ -265674 ], + "convertedRgb565" : [ -122 ] } }, "diagnostics" : [ ] @@ -762,14 +762,14 @@ "last_modified" : 1774359772456, "fingerprint" : "eeb7cc665386299403b7be1c272375d5077f3647c587f8033aa8c9275f840562", "metadata" : { - "palette" : { - "originalArgb8888" : [ -265674 ], - "convertedRgb565" : [ -122 ] - }, "tile" : { "width" : 32, "height" : 32, "paletteIndices" : "AQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAAAAAAAAAAABAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEAAAAAAAAAAAEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQAAAAAAAAAAAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAAAAAAAAAAABAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEAAAAAAAAAAAEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQAAAAAAAAAAAQEBAQEBAQEBAQEBAAAAAAAAAAAAAAAAAAAAAAAAAAABAQEBAQEBAQEBAQEAAAAAAAAAAAAAAAAAAAAAAAAAAAEBAQEBAQEBAQEBAQAAAAAAAAAAAAAAAAAAAAAAAAAAAQEBAQEBAQEBAQEBAAAAAAAAAAAAAAAAAAAAAAAAAAABAQEBAQEBAQEBAQEAAAAAAAAAAAAAAAAAAAAAAAAAAAEBAQEBAQEBAQEBAQAAAAAAAAAAAAAAAAAAAAAAAAAAAQEBAQEBAQEBAQEBAAAAAAAAAAAAAAAAAAAAAAAAAAABAQEBAQEBAQEBAQEAAAAAAAAAAAAAAAAAAAAAAAAAAAEBAQEBAQEBAQEBAQAAAAAAAAAAAAAAAAAAAQEBAQEBAQEBAQEBAQEBAQEBAAAAAAAAAAAAAAAAAAABAQEBAQEBAQEBAQEBAQEBAQEAAAAAAAAAAAAAAAAAAAEBAQEBAQEBAQEBAQEBAQEBAQAAAAAAAAAAAAAAAAAAAQEBAQEBAQEBAQEBAAAAAAAAAAAAAAAAAAAAAAAAAAABAQEBAQEBAQEBAQEAAAAAAAAAAAAAAAAAAAAAAAAAAAEBAQEBAQEBAQEBAQAAAAAAAAAAAAAAAAAAAQEBAQEBAQEBAQEBAQEBAQEBAAAAAAAAAAAAAAAAAAABAQEBAQEBAQEBAQEBAQEBAQEAAAAAAAAAAAAAAAAAAAEBAQEBAQEBAQEBAQEBAQEBAQAAAAAAAAAAAAAAAAAAAQEBAQEBAQEBAQEBAQEBAQEBAAAAAAAAAAAAAAAAAAABAQEBAQEBAQEBAQEBAQEBAQEAAAAAAAAAAAAAAAAAAAEBAQEBAQEBAQEBAQ==" + }, + "palette" : { + "originalArgb8888" : [ -265674 ], + "convertedRgb565" : [ -122 ] } }, "diagnostics" : [ ] @@ -780,14 +780,14 @@ "last_modified" : 1774359772458, "fingerprint" : "eeb7cc665386299403b7be1c272375d5077f3647c587f8033aa8c9275f840562", "metadata" : { - "palette" : { - "originalArgb8888" : [ -265674 ], - "convertedRgb565" : [ -122 ] - }, "tile" : { "width" : 32, "height" : 32, "paletteIndices" : "AQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAAAAAAAAAAABAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEAAAAAAAAAAAEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQAAAAAAAAAAAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAAAAAAAAAAABAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEAAAAAAAAAAAEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQAAAAAAAAAAAQEBAQEBAQEBAQEBAAAAAAAAAAAAAAAAAAAAAAAAAAABAQEBAQEBAQEBAQEAAAAAAAAAAAAAAAAAAAAAAAAAAAEBAQEBAQEBAQEBAQAAAAAAAAAAAAAAAAAAAAAAAAAAAQEBAQEBAQEBAQEBAAAAAAAAAAAAAAAAAAAAAAAAAAABAQEBAQEBAQEBAQEAAAAAAAAAAAAAAAAAAAAAAAAAAAEBAQEBAQEBAQEBAQAAAAAAAAAAAAAAAAAAAAAAAAAAAQEBAQEBAQEBAQEBAAAAAAAAAAAAAAAAAAAAAAAAAAABAQEBAQEBAQEBAQEAAAAAAAAAAAAAAAAAAAAAAAAAAAEBAQEBAQEBAQEBAQAAAAAAAAAAAAAAAAAAAQEBAQEBAQEBAQEBAQEBAQEBAAAAAAAAAAAAAAAAAAABAQEBAQEBAQEBAQEBAQEBAQEAAAAAAAAAAAAAAAAAAAEBAQEBAQEBAQEBAQEBAQEBAQAAAAAAAAAAAAAAAAAAAQEBAQEBAQEBAQEBAAAAAAAAAAAAAAAAAAAAAAAAAAABAQEBAQEBAQEBAQEAAAAAAAAAAAAAAAAAAAAAAAAAAAEBAQEBAQEBAQEBAQAAAAAAAAAAAAAAAAAAAQEBAQEBAQEBAQEBAQEBAQEBAAAAAAAAAAAAAAAAAAABAQEBAQEBAQEBAQEBAQEBAQEAAAAAAAAAAAAAAAAAAAEBAQEBAQEBAQEBAQEBAQEBAQAAAAAAAAAAAAAAAAAAAQEBAQEBAQEBAQEBAQEBAQEBAAAAAAAAAAAAAAAAAAABAQEBAQEBAQEBAQEBAQEBAQEAAAAAAAAAAAAAAAAAAAEBAQEBAQEBAQEBAQ==" + }, + "palette" : { + "originalArgb8888" : [ -265674 ], + "convertedRgb565" : [ -122 ] } }, "diagnostics" : [ ] @@ -798,14 +798,14 @@ "last_modified" : 1774359772459, "fingerprint" : "eeb7cc665386299403b7be1c272375d5077f3647c587f8033aa8c9275f840562", "metadata" : { - "palette" : { - "originalArgb8888" : [ -265674 ], - "convertedRgb565" : [ -122 ] - }, "tile" : { "width" : 32, "height" : 32, "paletteIndices" : "AQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAAAAAAAAAAABAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEAAAAAAAAAAAEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQAAAAAAAAAAAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAAAAAAAAAAABAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEAAAAAAAAAAAEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQAAAAAAAAAAAQEBAQEBAQEBAQEBAAAAAAAAAAAAAAAAAAAAAAAAAAABAQEBAQEBAQEBAQEAAAAAAAAAAAAAAAAAAAAAAAAAAAEBAQEBAQEBAQEBAQAAAAAAAAAAAAAAAAAAAAAAAAAAAQEBAQEBAQEBAQEBAAAAAAAAAAAAAAAAAAAAAAAAAAABAQEBAQEBAQEBAQEAAAAAAAAAAAAAAAAAAAAAAAAAAAEBAQEBAQEBAQEBAQAAAAAAAAAAAAAAAAAAAAAAAAAAAQEBAQEBAQEBAQEBAAAAAAAAAAAAAAAAAAAAAAAAAAABAQEBAQEBAQEBAQEAAAAAAAAAAAAAAAAAAAAAAAAAAAEBAQEBAQEBAQEBAQAAAAAAAAAAAAAAAAAAAQEBAQEBAQEBAQEBAQEBAQEBAAAAAAAAAAAAAAAAAAABAQEBAQEBAQEBAQEBAQEBAQEAAAAAAAAAAAAAAAAAAAEBAQEBAQEBAQEBAQEBAQEBAQAAAAAAAAAAAAAAAAAAAQEBAQEBAQEBAQEBAAAAAAAAAAAAAAAAAAAAAAAAAAABAQEBAQEBAQEBAQEAAAAAAAAAAAAAAAAAAAAAAAAAAAEBAQEBAQEBAQEBAQAAAAAAAAAAAAAAAAAAAQEBAQEBAQEBAQEBAQEBAQEBAAAAAAAAAAAAAAAAAAABAQEBAQEBAQEBAQEBAQEBAQEAAAAAAAAAAAAAAAAAAAEBAQEBAQEBAQEBAQEBAQEBAQAAAAAAAAAAAAAAAAAAAQEBAQEBAQEBAQEBAQEBAQEBAAAAAAAAAAAAAAAAAAABAQEBAQEBAQEBAQEBAQEBAQEAAAAAAAAAAAAAAAAAAAEBAQEBAQEBAQEBAQ==" + }, + "palette" : { + "originalArgb8888" : [ -265674 ], + "convertedRgb565" : [ -122 ] } }, "diagnostics" : [ ] @@ -816,14 +816,14 @@ "last_modified" : 1774359772460, "fingerprint" : "eeb7cc665386299403b7be1c272375d5077f3647c587f8033aa8c9275f840562", "metadata" : { - "palette" : { - "originalArgb8888" : [ -265674 ], - "convertedRgb565" : [ -122 ] - }, "tile" : { "width" : 32, "height" : 32, "paletteIndices" : "AQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAAAAAAAAAAABAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEAAAAAAAAAAAEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQAAAAAAAAAAAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAAAAAAAAAAABAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEAAAAAAAAAAAEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQAAAAAAAAAAAQEBAQEBAQEBAQEBAAAAAAAAAAAAAAAAAAAAAAAAAAABAQEBAQEBAQEBAQEAAAAAAAAAAAAAAAAAAAAAAAAAAAEBAQEBAQEBAQEBAQAAAAAAAAAAAAAAAAAAAAAAAAAAAQEBAQEBAQEBAQEBAAAAAAAAAAAAAAAAAAAAAAAAAAABAQEBAQEBAQEBAQEAAAAAAAAAAAAAAAAAAAAAAAAAAAEBAQEBAQEBAQEBAQAAAAAAAAAAAAAAAAAAAAAAAAAAAQEBAQEBAQEBAQEBAAAAAAAAAAAAAAAAAAAAAAAAAAABAQEBAQEBAQEBAQEAAAAAAAAAAAAAAAAAAAAAAAAAAAEBAQEBAQEBAQEBAQAAAAAAAAAAAAAAAAAAAQEBAQEBAQEBAQEBAQEBAQEBAAAAAAAAAAAAAAAAAAABAQEBAQEBAQEBAQEBAQEBAQEAAAAAAAAAAAAAAAAAAAEBAQEBAQEBAQEBAQEBAQEBAQAAAAAAAAAAAAAAAAAAAQEBAQEBAQEBAQEBAAAAAAAAAAAAAAAAAAAAAAAAAAABAQEBAQEBAQEBAQEAAAAAAAAAAAAAAAAAAAAAAAAAAAEBAQEBAQEBAQEBAQAAAAAAAAAAAAAAAAAAAQEBAQEBAQEBAQEBAQEBAQEBAAAAAAAAAAAAAAAAAAABAQEBAQEBAQEBAQEBAQEBAQEAAAAAAAAAAAAAAAAAAAEBAQEBAQEBAQEBAQEBAQEBAQAAAAAAAAAAAAAAAAAAAQEBAQEBAQEBAQEBAQEBAQEBAAAAAAAAAAAAAAAAAAABAQEBAQEBAQEBAQEBAQEBAQEAAAAAAAAAAAAAAAAAAAEBAQEBAQEBAQEBAQ==" + }, + "palette" : { + "originalArgb8888" : [ -265674 ], + "convertedRgb565" : [ -122 ] } }, "diagnostics" : [ ] @@ -834,14 +834,14 @@ "last_modified" : 1774359772461, "fingerprint" : "eeb7cc665386299403b7be1c272375d5077f3647c587f8033aa8c9275f840562", "metadata" : { - "palette" : { - "originalArgb8888" : [ -265674 ], - "convertedRgb565" : [ -122 ] - }, "tile" : { "width" : 32, "height" : 32, "paletteIndices" : "AQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAAAAAAAAAAABAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEAAAAAAAAAAAEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQAAAAAAAAAAAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAAAAAAAAAAABAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEAAAAAAAAAAAEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQAAAAAAAAAAAQEBAQEBAQEBAQEBAAAAAAAAAAAAAAAAAAAAAAAAAAABAQEBAQEBAQEBAQEAAAAAAAAAAAAAAAAAAAAAAAAAAAEBAQEBAQEBAQEBAQAAAAAAAAAAAAAAAAAAAAAAAAAAAQEBAQEBAQEBAQEBAAAAAAAAAAAAAAAAAAAAAAAAAAABAQEBAQEBAQEBAQEAAAAAAAAAAAAAAAAAAAAAAAAAAAEBAQEBAQEBAQEBAQAAAAAAAAAAAAAAAAAAAAAAAAAAAQEBAQEBAQEBAQEBAAAAAAAAAAAAAAAAAAAAAAAAAAABAQEBAQEBAQEBAQEAAAAAAAAAAAAAAAAAAAAAAAAAAAEBAQEBAQEBAQEBAQAAAAAAAAAAAAAAAAAAAQEBAQEBAQEBAQEBAQEBAQEBAAAAAAAAAAAAAAAAAAABAQEBAQEBAQEBAQEBAQEBAQEAAAAAAAAAAAAAAAAAAAEBAQEBAQEBAQEBAQEBAQEBAQAAAAAAAAAAAAAAAAAAAQEBAQEBAQEBAQEBAAAAAAAAAAAAAAAAAAAAAAAAAAABAQEBAQEBAQEBAQEAAAAAAAAAAAAAAAAAAAAAAAAAAAEBAQEBAQEBAQEBAQAAAAAAAAAAAAAAAAAAAQEBAQEBAQEBAQEBAQEBAQEBAAAAAAAAAAAAAAAAAAABAQEBAQEBAQEBAQEBAQEBAQEAAAAAAAAAAAAAAAAAAAEBAQEBAQEBAQEBAQEBAQEBAQAAAAAAAAAAAAAAAAAAAQEBAQEBAQEBAQEBAQEBAQEBAAAAAAAAAAAAAAAAAAABAQEBAQEBAQEBAQEBAQEBAQEAAAAAAAAAAAAAAAAAAAEBAQEBAQEBAQEBAQ==" + }, + "palette" : { + "originalArgb8888" : [ -265674 ], + "convertedRgb565" : [ -122 ] } }, "diagnostics" : [ ] @@ -852,14 +852,14 @@ "last_modified" : 1774359772463, "fingerprint" : "eeb7cc665386299403b7be1c272375d5077f3647c587f8033aa8c9275f840562", "metadata" : { - "palette" : { - "originalArgb8888" : [ -265674 ], - "convertedRgb565" : [ -122 ] - }, "tile" : { "width" : 32, "height" : 32, "paletteIndices" : "AQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAAAAAAAAAAABAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEAAAAAAAAAAAEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQAAAAAAAAAAAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAAAAAAAAAAABAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEAAAAAAAAAAAEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQAAAAAAAAAAAQEBAQEBAQEBAQEBAAAAAAAAAAAAAAAAAAAAAAAAAAABAQEBAQEBAQEBAQEAAAAAAAAAAAAAAAAAAAAAAAAAAAEBAQEBAQEBAQEBAQAAAAAAAAAAAAAAAAAAAAAAAAAAAQEBAQEBAQEBAQEBAAAAAAAAAAAAAAAAAAAAAAAAAAABAQEBAQEBAQEBAQEAAAAAAAAAAAAAAAAAAAAAAAAAAAEBAQEBAQEBAQEBAQAAAAAAAAAAAAAAAAAAAAAAAAAAAQEBAQEBAQEBAQEBAAAAAAAAAAAAAAAAAAAAAAAAAAABAQEBAQEBAQEBAQEAAAAAAAAAAAAAAAAAAAAAAAAAAAEBAQEBAQEBAQEBAQAAAAAAAAAAAAAAAAAAAQEBAQEBAQEBAQEBAQEBAQEBAAAAAAAAAAAAAAAAAAABAQEBAQEBAQEBAQEBAQEBAQEAAAAAAAAAAAAAAAAAAAEBAQEBAQEBAQEBAQEBAQEBAQAAAAAAAAAAAAAAAAAAAQEBAQEBAQEBAQEBAAAAAAAAAAAAAAAAAAAAAAAAAAABAQEBAQEBAQEBAQEAAAAAAAAAAAAAAAAAAAAAAAAAAAEBAQEBAQEBAQEBAQAAAAAAAAAAAAAAAAAAAQEBAQEBAQEBAQEBAQEBAQEBAAAAAAAAAAAAAAAAAAABAQEBAQEBAQEBAQEBAQEBAQEAAAAAAAAAAAAAAAAAAAEBAQEBAQEBAQEBAQEBAQEBAQAAAAAAAAAAAAAAAAAAAQEBAQEBAQEBAQEBAQEBAQEBAAAAAAAAAAAAAAAAAAABAQEBAQEBAQEBAQEBAQEBAQEAAAAAAAAAAAAAAAAAAAEBAQEBAQEBAQEBAQ==" + }, + "palette" : { + "originalArgb8888" : [ -265674 ], + "convertedRgb565" : [ -122 ] } }, "diagnostics" : [ ] @@ -870,14 +870,14 @@ "last_modified" : 1774359772464, "fingerprint" : "eeb7cc665386299403b7be1c272375d5077f3647c587f8033aa8c9275f840562", "metadata" : { - "palette" : { - "originalArgb8888" : [ -265674 ], - "convertedRgb565" : [ -122 ] - }, "tile" : { "width" : 32, "height" : 32, "paletteIndices" : "AQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAAAAAAAAAAABAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEAAAAAAAAAAAEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQAAAAAAAAAAAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAAAAAAAAAAABAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEAAAAAAAAAAAEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQAAAAAAAAAAAQEBAQEBAQEBAQEBAAAAAAAAAAAAAAAAAAAAAAAAAAABAQEBAQEBAQEBAQEAAAAAAAAAAAAAAAAAAAAAAAAAAAEBAQEBAQEBAQEBAQAAAAAAAAAAAAAAAAAAAAAAAAAAAQEBAQEBAQEBAQEBAAAAAAAAAAAAAAAAAAAAAAAAAAABAQEBAQEBAQEBAQEAAAAAAAAAAAAAAAAAAAAAAAAAAAEBAQEBAQEBAQEBAQAAAAAAAAAAAAAAAAAAAAAAAAAAAQEBAQEBAQEBAQEBAAAAAAAAAAAAAAAAAAAAAAAAAAABAQEBAQEBAQEBAQEAAAAAAAAAAAAAAAAAAAAAAAAAAAEBAQEBAQEBAQEBAQAAAAAAAAAAAAAAAAAAAQEBAQEBAQEBAQEBAQEBAQEBAAAAAAAAAAAAAAAAAAABAQEBAQEBAQEBAQEBAQEBAQEAAAAAAAAAAAAAAAAAAAEBAQEBAQEBAQEBAQEBAQEBAQAAAAAAAAAAAAAAAAAAAQEBAQEBAQEBAQEBAAAAAAAAAAAAAAAAAAAAAAAAAAABAQEBAQEBAQEBAQEAAAAAAAAAAAAAAAAAAAAAAAAAAAEBAQEBAQEBAQEBAQAAAAAAAAAAAAAAAAAAAQEBAQEBAQEBAQEBAQEBAQEBAAAAAAAAAAAAAAAAAAABAQEBAQEBAQEBAQEBAQEBAQEAAAAAAAAAAAAAAAAAAAEBAQEBAQEBAQEBAQEBAQEBAQAAAAAAAAAAAAAAAAAAAQEBAQEBAQEBAQEBAQEBAQEBAAAAAAAAAAAAAAAAAAABAQEBAQEBAQEBAQEBAQEBAQEAAAAAAAAAAAAAAAAAAAEBAQEBAQEBAQEBAQ==" + }, + "palette" : { + "originalArgb8888" : [ -265674 ], + "convertedRgb565" : [ -122 ] } }, "diagnostics" : [ ] @@ -888,14 +888,14 @@ "last_modified" : 1774359772465, "fingerprint" : "eeb7cc665386299403b7be1c272375d5077f3647c587f8033aa8c9275f840562", "metadata" : { - "palette" : { - "originalArgb8888" : [ -265674 ], - "convertedRgb565" : [ -122 ] - }, "tile" : { "width" : 32, "height" : 32, "paletteIndices" : "AQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAAAAAAAAAAABAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEAAAAAAAAAAAEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQAAAAAAAAAAAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAAAAAAAAAAABAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEAAAAAAAAAAAEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQAAAAAAAAAAAQEBAQEBAQEBAQEBAAAAAAAAAAAAAAAAAAAAAAAAAAABAQEBAQEBAQEBAQEAAAAAAAAAAAAAAAAAAAAAAAAAAAEBAQEBAQEBAQEBAQAAAAAAAAAAAAAAAAAAAAAAAAAAAQEBAQEBAQEBAQEBAAAAAAAAAAAAAAAAAAAAAAAAAAABAQEBAQEBAQEBAQEAAAAAAAAAAAAAAAAAAAAAAAAAAAEBAQEBAQEBAQEBAQAAAAAAAAAAAAAAAAAAAAAAAAAAAQEBAQEBAQEBAQEBAAAAAAAAAAAAAAAAAAAAAAAAAAABAQEBAQEBAQEBAQEAAAAAAAAAAAAAAAAAAAAAAAAAAAEBAQEBAQEBAQEBAQAAAAAAAAAAAAAAAAAAAQEBAQEBAQEBAQEBAQEBAQEBAAAAAAAAAAAAAAAAAAABAQEBAQEBAQEBAQEBAQEBAQEAAAAAAAAAAAAAAAAAAAEBAQEBAQEBAQEBAQEBAQEBAQAAAAAAAAAAAAAAAAAAAQEBAQEBAQEBAQEBAAAAAAAAAAAAAAAAAAAAAAAAAAABAQEBAQEBAQEBAQEAAAAAAAAAAAAAAAAAAAAAAAAAAAEBAQEBAQEBAQEBAQAAAAAAAAAAAAAAAAAAAQEBAQEBAQEBAQEBAQEBAQEBAAAAAAAAAAAAAAAAAAABAQEBAQEBAQEBAQEBAQEBAQEAAAAAAAAAAAAAAAAAAAEBAQEBAQEBAQEBAQEBAQEBAQAAAAAAAAAAAAAAAAAAAQEBAQEBAQEBAQEBAQEBAQEBAAAAAAAAAAAAAAAAAAABAQEBAQEBAQEBAQEBAQEBAQEAAAAAAAAAAAAAAAAAAAEBAQEBAQEBAQEBAQ==" + }, + "palette" : { + "originalArgb8888" : [ -265674 ], + "convertedRgb565" : [ -122 ] } }, "diagnostics" : [ ] @@ -906,14 +906,14 @@ "last_modified" : 1774359772467, "fingerprint" : "eeb7cc665386299403b7be1c272375d5077f3647c587f8033aa8c9275f840562", "metadata" : { - "palette" : { - "originalArgb8888" : [ -265674 ], - "convertedRgb565" : [ -122 ] - }, "tile" : { "width" : 32, "height" : 32, "paletteIndices" : "AQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAAAAAAAAAAABAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEAAAAAAAAAAAEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQAAAAAAAAAAAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAAAAAAAAAAABAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEAAAAAAAAAAAEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQAAAAAAAAAAAQEBAQEBAQEBAQEBAAAAAAAAAAAAAAAAAAAAAAAAAAABAQEBAQEBAQEBAQEAAAAAAAAAAAAAAAAAAAAAAAAAAAEBAQEBAQEBAQEBAQAAAAAAAAAAAAAAAAAAAAAAAAAAAQEBAQEBAQEBAQEBAAAAAAAAAAAAAAAAAAAAAAAAAAABAQEBAQEBAQEBAQEAAAAAAAAAAAAAAAAAAAAAAAAAAAEBAQEBAQEBAQEBAQAAAAAAAAAAAAAAAAAAAAAAAAAAAQEBAQEBAQEBAQEBAAAAAAAAAAAAAAAAAAAAAAAAAAABAQEBAQEBAQEBAQEAAAAAAAAAAAAAAAAAAAAAAAAAAAEBAQEBAQEBAQEBAQAAAAAAAAAAAAAAAAAAAQEBAQEBAQEBAQEBAQEBAQEBAAAAAAAAAAAAAAAAAAABAQEBAQEBAQEBAQEBAQEBAQEAAAAAAAAAAAAAAAAAAAEBAQEBAQEBAQEBAQEBAQEBAQAAAAAAAAAAAAAAAAAAAQEBAQEBAQEBAQEBAAAAAAAAAAAAAAAAAAAAAAAAAAABAQEBAQEBAQEBAQEAAAAAAAAAAAAAAAAAAAAAAAAAAAEBAQEBAQEBAQEBAQAAAAAAAAAAAAAAAAAAAQEBAQEBAQEBAQEBAQEBAQEBAAAAAAAAAAAAAAAAAAABAQEBAQEBAQEBAQEBAQEBAQEAAAAAAAAAAAAAAAAAAAEBAQEBAQEBAQEBAQEBAQEBAQAAAAAAAAAAAAAAAAAAAQEBAQEBAQEBAQEBAQEBAQEBAAAAAAAAAAAAAAAAAAABAQEBAQEBAQEBAQEBAQEBAQEAAAAAAAAAAAAAAAAAAAEBAQEBAQEBAQEBAQ==" + }, + "palette" : { + "originalArgb8888" : [ -265674 ], + "convertedRgb565" : [ -122 ] } }, "diagnostics" : [ ] @@ -924,14 +924,14 @@ "last_modified" : 1774359772468, "fingerprint" : "eeb7cc665386299403b7be1c272375d5077f3647c587f8033aa8c9275f840562", "metadata" : { - "palette" : { - "originalArgb8888" : [ -265674 ], - "convertedRgb565" : [ -122 ] - }, "tile" : { "width" : 32, "height" : 32, "paletteIndices" : "AQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAAAAAAAAAAABAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEAAAAAAAAAAAEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQAAAAAAAAAAAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAAAAAAAAAAABAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEAAAAAAAAAAAEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQAAAAAAAAAAAQEBAQEBAQEBAQEBAAAAAAAAAAAAAAAAAAAAAAAAAAABAQEBAQEBAQEBAQEAAAAAAAAAAAAAAAAAAAAAAAAAAAEBAQEBAQEBAQEBAQAAAAAAAAAAAAAAAAAAAAAAAAAAAQEBAQEBAQEBAQEBAAAAAAAAAAAAAAAAAAAAAAAAAAABAQEBAQEBAQEBAQEAAAAAAAAAAAAAAAAAAAAAAAAAAAEBAQEBAQEBAQEBAQAAAAAAAAAAAAAAAAAAAAAAAAAAAQEBAQEBAQEBAQEBAAAAAAAAAAAAAAAAAAAAAAAAAAABAQEBAQEBAQEBAQEAAAAAAAAAAAAAAAAAAAAAAAAAAAEBAQEBAQEBAQEBAQAAAAAAAAAAAAAAAAAAAQEBAQEBAQEBAQEBAQEBAQEBAAAAAAAAAAAAAAAAAAABAQEBAQEBAQEBAQEBAQEBAQEAAAAAAAAAAAAAAAAAAAEBAQEBAQEBAQEBAQEBAQEBAQAAAAAAAAAAAAAAAAAAAQEBAQEBAQEBAQEBAAAAAAAAAAAAAAAAAAAAAAAAAAABAQEBAQEBAQEBAQEAAAAAAAAAAAAAAAAAAAAAAAAAAAEBAQEBAQEBAQEBAQAAAAAAAAAAAAAAAAAAAQEBAQEBAQEBAQEBAQEBAQEBAAAAAAAAAAAAAAAAAAABAQEBAQEBAQEBAQEBAQEBAQEAAAAAAAAAAAAAAAAAAAEBAQEBAQEBAQEBAQEBAQEBAQAAAAAAAAAAAAAAAAAAAQEBAQEBAQEBAQEBAQEBAQEBAAAAAAAAAAAAAAAAAAABAQEBAQEBAQEBAQEBAQEBAQEAAAAAAAAAAAAAAAAAAAEBAQEBAQEBAQEBAQ==" + }, + "palette" : { + "originalArgb8888" : [ -265674 ], + "convertedRgb565" : [ -122 ] } }, "diagnostics" : [ ] @@ -942,14 +942,14 @@ "last_modified" : 1774359772470, "fingerprint" : "eeb7cc665386299403b7be1c272375d5077f3647c587f8033aa8c9275f840562", "metadata" : { - "palette" : { - "originalArgb8888" : [ -265674 ], - "convertedRgb565" : [ -122 ] - }, "tile" : { "width" : 32, "height" : 32, "paletteIndices" : "AQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAAAAAAAAAAABAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEAAAAAAAAAAAEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQAAAAAAAAAAAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAAAAAAAAAAABAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEAAAAAAAAAAAEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQAAAAAAAAAAAQEBAQEBAQEBAQEBAAAAAAAAAAAAAAAAAAAAAAAAAAABAQEBAQEBAQEBAQEAAAAAAAAAAAAAAAAAAAAAAAAAAAEBAQEBAQEBAQEBAQAAAAAAAAAAAAAAAAAAAAAAAAAAAQEBAQEBAQEBAQEBAAAAAAAAAAAAAAAAAAAAAAAAAAABAQEBAQEBAQEBAQEAAAAAAAAAAAAAAAAAAAAAAAAAAAEBAQEBAQEBAQEBAQAAAAAAAAAAAAAAAAAAAAAAAAAAAQEBAQEBAQEBAQEBAAAAAAAAAAAAAAAAAAAAAAAAAAABAQEBAQEBAQEBAQEAAAAAAAAAAAAAAAAAAAAAAAAAAAEBAQEBAQEBAQEBAQAAAAAAAAAAAAAAAAAAAQEBAQEBAQEBAQEBAQEBAQEBAAAAAAAAAAAAAAAAAAABAQEBAQEBAQEBAQEBAQEBAQEAAAAAAAAAAAAAAAAAAAEBAQEBAQEBAQEBAQEBAQEBAQAAAAAAAAAAAAAAAAAAAQEBAQEBAQEBAQEBAAAAAAAAAAAAAAAAAAAAAAAAAAABAQEBAQEBAQEBAQEAAAAAAAAAAAAAAAAAAAAAAAAAAAEBAQEBAQEBAQEBAQAAAAAAAAAAAAAAAAAAAQEBAQEBAQEBAQEBAQEBAQEBAAAAAAAAAAAAAAAAAAABAQEBAQEBAQEBAQEBAQEBAQEAAAAAAAAAAAAAAAAAAAEBAQEBAQEBAQEBAQEBAQEBAQAAAAAAAAAAAAAAAAAAAQEBAQEBAQEBAQEBAQEBAQEBAAAAAAAAAAAAAAAAAAABAQEBAQEBAQEBAQEBAQEBAQEAAAAAAAAAAAAAAAAAAAEBAQEBAQEBAQEBAQ==" + }, + "palette" : { + "originalArgb8888" : [ -265674 ], + "convertedRgb565" : [ -122 ] } }, "diagnostics" : [ ] @@ -960,14 +960,14 @@ "last_modified" : 1774359772474, "fingerprint" : "eeb7cc665386299403b7be1c272375d5077f3647c587f8033aa8c9275f840562", "metadata" : { - "palette" : { - "originalArgb8888" : [ -265674 ], - "convertedRgb565" : [ -122 ] - }, "tile" : { "width" : 32, "height" : 32, "paletteIndices" : "AQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAAAAAAAAAAABAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEAAAAAAAAAAAEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQAAAAAAAAAAAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAAAAAAAAAAABAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEAAAAAAAAAAAEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQAAAAAAAAAAAQEBAQEBAQEBAQEBAAAAAAAAAAAAAAAAAAAAAAAAAAABAQEBAQEBAQEBAQEAAAAAAAAAAAAAAAAAAAAAAAAAAAEBAQEBAQEBAQEBAQAAAAAAAAAAAAAAAAAAAAAAAAAAAQEBAQEBAQEBAQEBAAAAAAAAAAAAAAAAAAAAAAAAAAABAQEBAQEBAQEBAQEAAAAAAAAAAAAAAAAAAAAAAAAAAAEBAQEBAQEBAQEBAQAAAAAAAAAAAAAAAAAAAAAAAAAAAQEBAQEBAQEBAQEBAAAAAAAAAAAAAAAAAAAAAAAAAAABAQEBAQEBAQEBAQEAAAAAAAAAAAAAAAAAAAAAAAAAAAEBAQEBAQEBAQEBAQAAAAAAAAAAAAAAAAAAAQEBAQEBAQEBAQEBAQEBAQEBAAAAAAAAAAAAAAAAAAABAQEBAQEBAQEBAQEBAQEBAQEAAAAAAAAAAAAAAAAAAAEBAQEBAQEBAQEBAQEBAQEBAQAAAAAAAAAAAAAAAAAAAQEBAQEBAQEBAQEBAAAAAAAAAAAAAAAAAAAAAAAAAAABAQEBAQEBAQEBAQEAAAAAAAAAAAAAAAAAAAAAAAAAAAEBAQEBAQEBAQEBAQAAAAAAAAAAAAAAAAAAAQEBAQEBAQEBAQEBAQEBAQEBAAAAAAAAAAAAAAAAAAABAQEBAQEBAQEBAQEBAQEBAQEAAAAAAAAAAAAAAAAAAAEBAQEBAQEBAQEBAQEBAQEBAQAAAAAAAAAAAAAAAAAAAQEBAQEBAQEBAQEBAQEBAQEBAAAAAAAAAAAAAAAAAAABAQEBAQEBAQEBAQEBAQEBAQEAAAAAAAAAAAAAAAAAAAEBAQEBAQEBAQEBAQ==" + }, + "palette" : { + "originalArgb8888" : [ -265674 ], + "convertedRgb565" : [ -122 ] } }, "diagnostics" : [ ] @@ -978,14 +978,14 @@ "last_modified" : 1774359772476, "fingerprint" : "eeb7cc665386299403b7be1c272375d5077f3647c587f8033aa8c9275f840562", "metadata" : { - "palette" : { - "originalArgb8888" : [ -265674 ], - "convertedRgb565" : [ -122 ] - }, "tile" : { "width" : 32, "height" : 32, "paletteIndices" : "AQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAAAAAAAAAAABAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEAAAAAAAAAAAEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQAAAAAAAAAAAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAAAAAAAAAAABAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEAAAAAAAAAAAEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQAAAAAAAAAAAQEBAQEBAQEBAQEBAAAAAAAAAAAAAAAAAAAAAAAAAAABAQEBAQEBAQEBAQEAAAAAAAAAAAAAAAAAAAAAAAAAAAEBAQEBAQEBAQEBAQAAAAAAAAAAAAAAAAAAAAAAAAAAAQEBAQEBAQEBAQEBAAAAAAAAAAAAAAAAAAAAAAAAAAABAQEBAQEBAQEBAQEAAAAAAAAAAAAAAAAAAAAAAAAAAAEBAQEBAQEBAQEBAQAAAAAAAAAAAAAAAAAAAAAAAAAAAQEBAQEBAQEBAQEBAAAAAAAAAAAAAAAAAAAAAAAAAAABAQEBAQEBAQEBAQEAAAAAAAAAAAAAAAAAAAAAAAAAAAEBAQEBAQEBAQEBAQAAAAAAAAAAAAAAAAAAAQEBAQEBAQEBAQEBAQEBAQEBAAAAAAAAAAAAAAAAAAABAQEBAQEBAQEBAQEBAQEBAQEAAAAAAAAAAAAAAAAAAAEBAQEBAQEBAQEBAQEBAQEBAQAAAAAAAAAAAAAAAAAAAQEBAQEBAQEBAQEBAAAAAAAAAAAAAAAAAAAAAAAAAAABAQEBAQEBAQEBAQEAAAAAAAAAAAAAAAAAAAAAAAAAAAEBAQEBAQEBAQEBAQAAAAAAAAAAAAAAAAAAAQEBAQEBAQEBAQEBAQEBAQEBAAAAAAAAAAAAAAAAAAABAQEBAQEBAQEBAQEBAQEBAQEAAAAAAAAAAAAAAAAAAAEBAQEBAQEBAQEBAQEBAQEBAQAAAAAAAAAAAAAAAAAAAQEBAQEBAQEBAQEBAQEBAQEBAAAAAAAAAAAAAAAAAAABAQEBAQEBAQEBAQEBAQEBAQEAAAAAAAAAAAAAAAAAAAEBAQEBAQEBAQEBAQ==" + }, + "palette" : { + "originalArgb8888" : [ -265674 ], + "convertedRgb565" : [ -122 ] } }, "diagnostics" : [ ] @@ -996,14 +996,14 @@ "last_modified" : 1774359772478, "fingerprint" : "eeb7cc665386299403b7be1c272375d5077f3647c587f8033aa8c9275f840562", "metadata" : { - "palette" : { - "originalArgb8888" : [ -265674 ], - "convertedRgb565" : [ -122 ] - }, "tile" : { "width" : 32, "height" : 32, "paletteIndices" : "AQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAAAAAAAAAAABAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEAAAAAAAAAAAEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQAAAAAAAAAAAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAAAAAAAAAAABAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEAAAAAAAAAAAEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQAAAAAAAAAAAQEBAQEBAQEBAQEBAAAAAAAAAAAAAAAAAAAAAAAAAAABAQEBAQEBAQEBAQEAAAAAAAAAAAAAAAAAAAAAAAAAAAEBAQEBAQEBAQEBAQAAAAAAAAAAAAAAAAAAAAAAAAAAAQEBAQEBAQEBAQEBAAAAAAAAAAAAAAAAAAAAAAAAAAABAQEBAQEBAQEBAQEAAAAAAAAAAAAAAAAAAAAAAAAAAAEBAQEBAQEBAQEBAQAAAAAAAAAAAAAAAAAAAAAAAAAAAQEBAQEBAQEBAQEBAAAAAAAAAAAAAAAAAAAAAAAAAAABAQEBAQEBAQEBAQEAAAAAAAAAAAAAAAAAAAAAAAAAAAEBAQEBAQEBAQEBAQAAAAAAAAAAAAAAAAAAAQEBAQEBAQEBAQEBAQEBAQEBAAAAAAAAAAAAAAAAAAABAQEBAQEBAQEBAQEBAQEBAQEAAAAAAAAAAAAAAAAAAAEBAQEBAQEBAQEBAQEBAQEBAQAAAAAAAAAAAAAAAAAAAQEBAQEBAQEBAQEBAAAAAAAAAAAAAAAAAAAAAAAAAAABAQEBAQEBAQEBAQEAAAAAAAAAAAAAAAAAAAAAAAAAAAEBAQEBAQEBAQEBAQAAAAAAAAAAAAAAAAAAAQEBAQEBAQEBAQEBAQEBAQEBAAAAAAAAAAAAAAAAAAABAQEBAQEBAQEBAQEBAQEBAQEAAAAAAAAAAAAAAAAAAAEBAQEBAQEBAQEBAQEBAQEBAQAAAAAAAAAAAAAAAAAAAQEBAQEBAQEBAQEBAQEBAQEBAAAAAAAAAAAAAAAAAAABAQEBAQEBAQEBAQEBAQEBAQEAAAAAAAAAAAAAAAAAAAEBAQEBAQEBAQEBAQ==" + }, + "palette" : { + "originalArgb8888" : [ -265674 ], + "convertedRgb565" : [ -122 ] } }, "diagnostics" : [ ] @@ -1014,14 +1014,14 @@ "last_modified" : 1774359772479, "fingerprint" : "eeb7cc665386299403b7be1c272375d5077f3647c587f8033aa8c9275f840562", "metadata" : { - "palette" : { - "originalArgb8888" : [ -265674 ], - "convertedRgb565" : [ -122 ] - }, "tile" : { "width" : 32, "height" : 32, "paletteIndices" : "AQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAAAAAAAAAAABAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEAAAAAAAAAAAEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQAAAAAAAAAAAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAAAAAAAAAAABAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEAAAAAAAAAAAEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQAAAAAAAAAAAQEBAQEBAQEBAQEBAAAAAAAAAAAAAAAAAAAAAAAAAAABAQEBAQEBAQEBAQEAAAAAAAAAAAAAAAAAAAAAAAAAAAEBAQEBAQEBAQEBAQAAAAAAAAAAAAAAAAAAAAAAAAAAAQEBAQEBAQEBAQEBAAAAAAAAAAAAAAAAAAAAAAAAAAABAQEBAQEBAQEBAQEAAAAAAAAAAAAAAAAAAAAAAAAAAAEBAQEBAQEBAQEBAQAAAAAAAAAAAAAAAAAAAAAAAAAAAQEBAQEBAQEBAQEBAAAAAAAAAAAAAAAAAAAAAAAAAAABAQEBAQEBAQEBAQEAAAAAAAAAAAAAAAAAAAAAAAAAAAEBAQEBAQEBAQEBAQAAAAAAAAAAAAAAAAAAAQEBAQEBAQEBAQEBAQEBAQEBAAAAAAAAAAAAAAAAAAABAQEBAQEBAQEBAQEBAQEBAQEAAAAAAAAAAAAAAAAAAAEBAQEBAQEBAQEBAQEBAQEBAQAAAAAAAAAAAAAAAAAAAQEBAQEBAQEBAQEBAAAAAAAAAAAAAAAAAAAAAAAAAAABAQEBAQEBAQEBAQEAAAAAAAAAAAAAAAAAAAAAAAAAAAEBAQEBAQEBAQEBAQAAAAAAAAAAAAAAAAAAAQEBAQEBAQEBAQEBAQEBAQEBAAAAAAAAAAAAAAAAAAABAQEBAQEBAQEBAQEBAQEBAQEAAAAAAAAAAAAAAAAAAAEBAQEBAQEBAQEBAQEBAQEBAQAAAAAAAAAAAAAAAAAAAQEBAQEBAQEBAQEBAQEBAQEBAAAAAAAAAAAAAAAAAAABAQEBAQEBAQEBAQEBAQEBAQEAAAAAAAAAAAAAAAAAAAEBAQEBAQEBAQEBAQ==" + }, + "palette" : { + "originalArgb8888" : [ -265674 ], + "convertedRgb565" : [ -122 ] } }, "diagnostics" : [ ] @@ -1032,14 +1032,14 @@ "last_modified" : 1774359772481, "fingerprint" : "eeb7cc665386299403b7be1c272375d5077f3647c587f8033aa8c9275f840562", "metadata" : { - "palette" : { - "originalArgb8888" : [ -265674 ], - "convertedRgb565" : [ -122 ] - }, "tile" : { "width" : 32, "height" : 32, "paletteIndices" : "AQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAAAAAAAAAAABAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEAAAAAAAAAAAEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQAAAAAAAAAAAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAAAAAAAAAAABAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEAAAAAAAAAAAEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQAAAAAAAAAAAQEBAQEBAQEBAQEBAAAAAAAAAAAAAAAAAAAAAAAAAAABAQEBAQEBAQEBAQEAAAAAAAAAAAAAAAAAAAAAAAAAAAEBAQEBAQEBAQEBAQAAAAAAAAAAAAAAAAAAAAAAAAAAAQEBAQEBAQEBAQEBAAAAAAAAAAAAAAAAAAAAAAAAAAABAQEBAQEBAQEBAQEAAAAAAAAAAAAAAAAAAAAAAAAAAAEBAQEBAQEBAQEBAQAAAAAAAAAAAAAAAAAAAAAAAAAAAQEBAQEBAQEBAQEBAAAAAAAAAAAAAAAAAAAAAAAAAAABAQEBAQEBAQEBAQEAAAAAAAAAAAAAAAAAAAAAAAAAAAEBAQEBAQEBAQEBAQAAAAAAAAAAAAAAAAAAAQEBAQEBAQEBAQEBAQEBAQEBAAAAAAAAAAAAAAAAAAABAQEBAQEBAQEBAQEBAQEBAQEAAAAAAAAAAAAAAAAAAAEBAQEBAQEBAQEBAQEBAQEBAQAAAAAAAAAAAAAAAAAAAQEBAQEBAQEBAQEBAAAAAAAAAAAAAAAAAAAAAAAAAAABAQEBAQEBAQEBAQEAAAAAAAAAAAAAAAAAAAAAAAAAAAEBAQEBAQEBAQEBAQAAAAAAAAAAAAAAAAAAAQEBAQEBAQEBAQEBAQEBAQEBAAAAAAAAAAAAAAAAAAABAQEBAQEBAQEBAQEBAQEBAQEAAAAAAAAAAAAAAAAAAAEBAQEBAQEBAQEBAQEBAQEBAQAAAAAAAAAAAAAAAAAAAQEBAQEBAQEBAQEBAQEBAQEBAAAAAAAAAAAAAAAAAAABAQEBAQEBAQEBAQEBAQEBAQEAAAAAAAAAAAAAAAAAAAEBAQEBAQEBAQEBAQ==" + }, + "palette" : { + "originalArgb8888" : [ -265674 ], + "convertedRgb565" : [ -122 ] } }, "diagnostics" : [ ] @@ -1050,14 +1050,14 @@ "last_modified" : 1774359772482, "fingerprint" : "eeb7cc665386299403b7be1c272375d5077f3647c587f8033aa8c9275f840562", "metadata" : { - "palette" : { - "originalArgb8888" : [ -265674 ], - "convertedRgb565" : [ -122 ] - }, "tile" : { "width" : 32, "height" : 32, "paletteIndices" : "AQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAAAAAAAAAAABAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEAAAAAAAAAAAEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQAAAAAAAAAAAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAAAAAAAAAAABAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEAAAAAAAAAAAEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQAAAAAAAAAAAQEBAQEBAQEBAQEBAAAAAAAAAAAAAAAAAAAAAAAAAAABAQEBAQEBAQEBAQEAAAAAAAAAAAAAAAAAAAAAAAAAAAEBAQEBAQEBAQEBAQAAAAAAAAAAAAAAAAAAAAAAAAAAAQEBAQEBAQEBAQEBAAAAAAAAAAAAAAAAAAAAAAAAAAABAQEBAQEBAQEBAQEAAAAAAAAAAAAAAAAAAAAAAAAAAAEBAQEBAQEBAQEBAQAAAAAAAAAAAAAAAAAAAAAAAAAAAQEBAQEBAQEBAQEBAAAAAAAAAAAAAAAAAAAAAAAAAAABAQEBAQEBAQEBAQEAAAAAAAAAAAAAAAAAAAAAAAAAAAEBAQEBAQEBAQEBAQAAAAAAAAAAAAAAAAAAAQEBAQEBAQEBAQEBAQEBAQEBAAAAAAAAAAAAAAAAAAABAQEBAQEBAQEBAQEBAQEBAQEAAAAAAAAAAAAAAAAAAAEBAQEBAQEBAQEBAQEBAQEBAQAAAAAAAAAAAAAAAAAAAQEBAQEBAQEBAQEBAAAAAAAAAAAAAAAAAAAAAAAAAAABAQEBAQEBAQEBAQEAAAAAAAAAAAAAAAAAAAAAAAAAAAEBAQEBAQEBAQEBAQAAAAAAAAAAAAAAAAAAAQEBAQEBAQEBAQEBAQEBAQEBAAAAAAAAAAAAAAAAAAABAQEBAQEBAQEBAQEBAQEBAQEAAAAAAAAAAAAAAAAAAAEBAQEBAQEBAQEBAQEBAQEBAQAAAAAAAAAAAAAAAAAAAQEBAQEBAQEBAQEBAQEBAQEBAAAAAAAAAAAAAAAAAAABAQEBAQEBAQEBAQEBAQEBAQEAAAAAAAAAAAAAAAAAAAEBAQEBAQEBAQEBAQ==" + }, + "palette" : { + "originalArgb8888" : [ -265674 ], + "convertedRgb565" : [ -122 ] } }, "diagnostics" : [ ] @@ -1068,14 +1068,14 @@ "last_modified" : 1774359772483, "fingerprint" : "eeb7cc665386299403b7be1c272375d5077f3647c587f8033aa8c9275f840562", "metadata" : { - "palette" : { - "originalArgb8888" : [ -265674 ], - "convertedRgb565" : [ -122 ] - }, "tile" : { "width" : 32, "height" : 32, "paletteIndices" : "AQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAAAAAAAAAAABAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEAAAAAAAAAAAEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQAAAAAAAAAAAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAAAAAAAAAAABAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEAAAAAAAAAAAEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQAAAAAAAAAAAQEBAQEBAQEBAQEBAAAAAAAAAAAAAAAAAAAAAAAAAAABAQEBAQEBAQEBAQEAAAAAAAAAAAAAAAAAAAAAAAAAAAEBAQEBAQEBAQEBAQAAAAAAAAAAAAAAAAAAAAAAAAAAAQEBAQEBAQEBAQEBAAAAAAAAAAAAAAAAAAAAAAAAAAABAQEBAQEBAQEBAQEAAAAAAAAAAAAAAAAAAAAAAAAAAAEBAQEBAQEBAQEBAQAAAAAAAAAAAAAAAAAAAAAAAAAAAQEBAQEBAQEBAQEBAAAAAAAAAAAAAAAAAAAAAAAAAAABAQEBAQEBAQEBAQEAAAAAAAAAAAAAAAAAAAAAAAAAAAEBAQEBAQEBAQEBAQAAAAAAAAAAAAAAAAAAAQEBAQEBAQEBAQEBAQEBAQEBAAAAAAAAAAAAAAAAAAABAQEBAQEBAQEBAQEBAQEBAQEAAAAAAAAAAAAAAAAAAAEBAQEBAQEBAQEBAQEBAQEBAQAAAAAAAAAAAAAAAAAAAQEBAQEBAQEBAQEBAAAAAAAAAAAAAAAAAAAAAAAAAAABAQEBAQEBAQEBAQEAAAAAAAAAAAAAAAAAAAAAAAAAAAEBAQEBAQEBAQEBAQAAAAAAAAAAAAAAAAAAAQEBAQEBAQEBAQEBAQEBAQEBAAAAAAAAAAAAAAAAAAABAQEBAQEBAQEBAQEBAQEBAQEAAAAAAAAAAAAAAAAAAAEBAQEBAQEBAQEBAQEBAQEBAQAAAAAAAAAAAAAAAAAAAQEBAQEBAQEBAQEBAQEBAQEBAAAAAAAAAAAAAAAAAAABAQEBAQEBAQEBAQEBAQEBAQEAAAAAAAAAAAAAAAAAAAEBAQEBAQEBAQEBAQ==" + }, + "palette" : { + "originalArgb8888" : [ -265674 ], + "convertedRgb565" : [ -122 ] } }, "diagnostics" : [ ] @@ -1086,14 +1086,14 @@ "last_modified" : 1774359772484, "fingerprint" : "eeb7cc665386299403b7be1c272375d5077f3647c587f8033aa8c9275f840562", "metadata" : { - "palette" : { - "originalArgb8888" : [ -265674 ], - "convertedRgb565" : [ -122 ] - }, "tile" : { "width" : 32, "height" : 32, "paletteIndices" : "AQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAAAAAAAAAAABAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEAAAAAAAAAAAEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQAAAAAAAAAAAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAAAAAAAAAAABAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEAAAAAAAAAAAEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQAAAAAAAAAAAQEBAQEBAQEBAQEBAAAAAAAAAAAAAAAAAAAAAAAAAAABAQEBAQEBAQEBAQEAAAAAAAAAAAAAAAAAAAAAAAAAAAEBAQEBAQEBAQEBAQAAAAAAAAAAAAAAAAAAAAAAAAAAAQEBAQEBAQEBAQEBAAAAAAAAAAAAAAAAAAAAAAAAAAABAQEBAQEBAQEBAQEAAAAAAAAAAAAAAAAAAAAAAAAAAAEBAQEBAQEBAQEBAQAAAAAAAAAAAAAAAAAAAAAAAAAAAQEBAQEBAQEBAQEBAAAAAAAAAAAAAAAAAAAAAAAAAAABAQEBAQEBAQEBAQEAAAAAAAAAAAAAAAAAAAAAAAAAAAEBAQEBAQEBAQEBAQAAAAAAAAAAAAAAAAAAAQEBAQEBAQEBAQEBAQEBAQEBAAAAAAAAAAAAAAAAAAABAQEBAQEBAQEBAQEBAQEBAQEAAAAAAAAAAAAAAAAAAAEBAQEBAQEBAQEBAQEBAQEBAQAAAAAAAAAAAAAAAAAAAQEBAQEBAQEBAQEBAAAAAAAAAAAAAAAAAAAAAAAAAAABAQEBAQEBAQEBAQEAAAAAAAAAAAAAAAAAAAAAAAAAAAEBAQEBAQEBAQEBAQAAAAAAAAAAAAAAAAAAAQEBAQEBAQEBAQEBAQEBAQEBAAAAAAAAAAAAAAAAAAABAQEBAQEBAQEBAQEBAQEBAQEAAAAAAAAAAAAAAAAAAAEBAQEBAQEBAQEBAQEBAQEBAQAAAAAAAAAAAAAAAAAAAQEBAQEBAQEBAQEBAQEBAQEBAAAAAAAAAAAAAAAAAAABAQEBAQEBAQEBAQEBAQEBAQEAAAAAAAAAAAAAAAAAAAEBAQEBAQEBAQEBAQ==" + }, + "palette" : { + "originalArgb8888" : [ -265674 ], + "convertedRgb565" : [ -122 ] } }, "diagnostics" : [ ] @@ -1104,14 +1104,14 @@ "last_modified" : 1774359772485, "fingerprint" : "eeb7cc665386299403b7be1c272375d5077f3647c587f8033aa8c9275f840562", "metadata" : { - "palette" : { - "originalArgb8888" : [ -265674 ], - "convertedRgb565" : [ -122 ] - }, "tile" : { "width" : 32, "height" : 32, "paletteIndices" : "AQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAAAAAAAAAAABAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEAAAAAAAAAAAEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQAAAAAAAAAAAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAAAAAAAAAAABAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEAAAAAAAAAAAEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQAAAAAAAAAAAQEBAQEBAQEBAQEBAAAAAAAAAAAAAAAAAAAAAAAAAAABAQEBAQEBAQEBAQEAAAAAAAAAAAAAAAAAAAAAAAAAAAEBAQEBAQEBAQEBAQAAAAAAAAAAAAAAAAAAAAAAAAAAAQEBAQEBAQEBAQEBAAAAAAAAAAAAAAAAAAAAAAAAAAABAQEBAQEBAQEBAQEAAAAAAAAAAAAAAAAAAAAAAAAAAAEBAQEBAQEBAQEBAQAAAAAAAAAAAAAAAAAAAAAAAAAAAQEBAQEBAQEBAQEBAAAAAAAAAAAAAAAAAAAAAAAAAAABAQEBAQEBAQEBAQEAAAAAAAAAAAAAAAAAAAAAAAAAAAEBAQEBAQEBAQEBAQAAAAAAAAAAAAAAAAAAAQEBAQEBAQEBAQEBAQEBAQEBAAAAAAAAAAAAAAAAAAABAQEBAQEBAQEBAQEBAQEBAQEAAAAAAAAAAAAAAAAAAAEBAQEBAQEBAQEBAQEBAQEBAQAAAAAAAAAAAAAAAAAAAQEBAQEBAQEBAQEBAAAAAAAAAAAAAAAAAAAAAAAAAAABAQEBAQEBAQEBAQEAAAAAAAAAAAAAAAAAAAAAAAAAAAEBAQEBAQEBAQEBAQAAAAAAAAAAAAAAAAAAAQEBAQEBAQEBAQEBAQEBAQEBAAAAAAAAAAAAAAAAAAABAQEBAQEBAQEBAQEBAQEBAQEAAAAAAAAAAAAAAAAAAAEBAQEBAQEBAQEBAQEBAQEBAQAAAAAAAAAAAAAAAAAAAQEBAQEBAQEBAQEBAQEBAQEBAAAAAAAAAAAAAAAAAAABAQEBAQEBAQEBAQEBAQEBAQEAAAAAAAAAAAAAAAAAAAEBAQEBAQEBAQEBAQ==" + }, + "palette" : { + "originalArgb8888" : [ -265674 ], + "convertedRgb565" : [ -122 ] } }, "diagnostics" : [ ] @@ -1122,14 +1122,14 @@ "last_modified" : 1774359772487, "fingerprint" : "eeb7cc665386299403b7be1c272375d5077f3647c587f8033aa8c9275f840562", "metadata" : { - "palette" : { - "originalArgb8888" : [ -265674 ], - "convertedRgb565" : [ -122 ] - }, "tile" : { "width" : 32, "height" : 32, "paletteIndices" : "AQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAAAAAAAAAAABAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEAAAAAAAAAAAEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQAAAAAAAAAAAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAAAAAAAAAAABAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEAAAAAAAAAAAEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQAAAAAAAAAAAQEBAQEBAQEBAQEBAAAAAAAAAAAAAAAAAAAAAAAAAAABAQEBAQEBAQEBAQEAAAAAAAAAAAAAAAAAAAAAAAAAAAEBAQEBAQEBAQEBAQAAAAAAAAAAAAAAAAAAAAAAAAAAAQEBAQEBAQEBAQEBAAAAAAAAAAAAAAAAAAAAAAAAAAABAQEBAQEBAQEBAQEAAAAAAAAAAAAAAAAAAAAAAAAAAAEBAQEBAQEBAQEBAQAAAAAAAAAAAAAAAAAAAAAAAAAAAQEBAQEBAQEBAQEBAAAAAAAAAAAAAAAAAAAAAAAAAAABAQEBAQEBAQEBAQEAAAAAAAAAAAAAAAAAAAAAAAAAAAEBAQEBAQEBAQEBAQAAAAAAAAAAAAAAAAAAAQEBAQEBAQEBAQEBAQEBAQEBAAAAAAAAAAAAAAAAAAABAQEBAQEBAQEBAQEBAQEBAQEAAAAAAAAAAAAAAAAAAAEBAQEBAQEBAQEBAQEBAQEBAQAAAAAAAAAAAAAAAAAAAQEBAQEBAQEBAQEBAAAAAAAAAAAAAAAAAAAAAAAAAAABAQEBAQEBAQEBAQEAAAAAAAAAAAAAAAAAAAAAAAAAAAEBAQEBAQEBAQEBAQAAAAAAAAAAAAAAAAAAAQEBAQEBAQEBAQEBAQEBAQEBAAAAAAAAAAAAAAAAAAABAQEBAQEBAQEBAQEBAQEBAQEAAAAAAAAAAAAAAAAAAAEBAQEBAQEBAQEBAQEBAQEBAQAAAAAAAAAAAAAAAAAAAQEBAQEBAQEBAQEBAQEBAQEBAAAAAAAAAAAAAAAAAAABAQEBAQEBAQEBAQEBAQEBAQEAAAAAAAAAAAAAAAAAAAEBAQEBAQEBAQEBAQ==" + }, + "palette" : { + "originalArgb8888" : [ -265674 ], + "convertedRgb565" : [ -122 ] } }, "diagnostics" : [ ] @@ -1140,14 +1140,14 @@ "last_modified" : 1774359772488, "fingerprint" : "eeb7cc665386299403b7be1c272375d5077f3647c587f8033aa8c9275f840562", "metadata" : { - "palette" : { - "originalArgb8888" : [ -265674 ], - "convertedRgb565" : [ -122 ] - }, "tile" : { "width" : 32, "height" : 32, "paletteIndices" : "AQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAAAAAAAAAAABAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEAAAAAAAAAAAEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQAAAAAAAAAAAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAAAAAAAAAAABAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEAAAAAAAAAAAEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQAAAAAAAAAAAQEBAQEBAQEBAQEBAAAAAAAAAAAAAAAAAAAAAAAAAAABAQEBAQEBAQEBAQEAAAAAAAAAAAAAAAAAAAAAAAAAAAEBAQEBAQEBAQEBAQAAAAAAAAAAAAAAAAAAAAAAAAAAAQEBAQEBAQEBAQEBAAAAAAAAAAAAAAAAAAAAAAAAAAABAQEBAQEBAQEBAQEAAAAAAAAAAAAAAAAAAAAAAAAAAAEBAQEBAQEBAQEBAQAAAAAAAAAAAAAAAAAAAAAAAAAAAQEBAQEBAQEBAQEBAAAAAAAAAAAAAAAAAAAAAAAAAAABAQEBAQEBAQEBAQEAAAAAAAAAAAAAAAAAAAAAAAAAAAEBAQEBAQEBAQEBAQAAAAAAAAAAAAAAAAAAAQEBAQEBAQEBAQEBAQEBAQEBAAAAAAAAAAAAAAAAAAABAQEBAQEBAQEBAQEBAQEBAQEAAAAAAAAAAAAAAAAAAAEBAQEBAQEBAQEBAQEBAQEBAQAAAAAAAAAAAAAAAAAAAQEBAQEBAQEBAQEBAAAAAAAAAAAAAAAAAAAAAAAAAAABAQEBAQEBAQEBAQEAAAAAAAAAAAAAAAAAAAAAAAAAAAEBAQEBAQEBAQEBAQAAAAAAAAAAAAAAAAAAAQEBAQEBAQEBAQEBAQEBAQEBAAAAAAAAAAAAAAAAAAABAQEBAQEBAQEBAQEBAQEBAQEAAAAAAAAAAAAAAAAAAAEBAQEBAQEBAQEBAQEBAQEBAQAAAAAAAAAAAAAAAAAAAQEBAQEBAQEBAQEBAQEBAQEBAAAAAAAAAAAAAAAAAAABAQEBAQEBAQEBAQEBAQEBAQEAAAAAAAAAAAAAAAAAAAEBAQEBAQEBAQEBAQ==" + }, + "palette" : { + "originalArgb8888" : [ -265674 ], + "convertedRgb565" : [ -122 ] } }, "diagnostics" : [ ] @@ -1158,14 +1158,14 @@ "last_modified" : 1774359772489, "fingerprint" : "eeb7cc665386299403b7be1c272375d5077f3647c587f8033aa8c9275f840562", "metadata" : { - "palette" : { - "originalArgb8888" : [ -265674 ], - "convertedRgb565" : [ -122 ] - }, "tile" : { "width" : 32, "height" : 32, "paletteIndices" : "AQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAAAAAAAAAAABAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEAAAAAAAAAAAEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQAAAAAAAAAAAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAAAAAAAAAAABAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEAAAAAAAAAAAEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQAAAAAAAAAAAQEBAQEBAQEBAQEBAAAAAAAAAAAAAAAAAAAAAAAAAAABAQEBAQEBAQEBAQEAAAAAAAAAAAAAAAAAAAAAAAAAAAEBAQEBAQEBAQEBAQAAAAAAAAAAAAAAAAAAAAAAAAAAAQEBAQEBAQEBAQEBAAAAAAAAAAAAAAAAAAAAAAAAAAABAQEBAQEBAQEBAQEAAAAAAAAAAAAAAAAAAAAAAAAAAAEBAQEBAQEBAQEBAQAAAAAAAAAAAAAAAAAAAAAAAAAAAQEBAQEBAQEBAQEBAAAAAAAAAAAAAAAAAAAAAAAAAAABAQEBAQEBAQEBAQEAAAAAAAAAAAAAAAAAAAAAAAAAAAEBAQEBAQEBAQEBAQAAAAAAAAAAAAAAAAAAAQEBAQEBAQEBAQEBAQEBAQEBAAAAAAAAAAAAAAAAAAABAQEBAQEBAQEBAQEBAQEBAQEAAAAAAAAAAAAAAAAAAAEBAQEBAQEBAQEBAQEBAQEBAQAAAAAAAAAAAAAAAAAAAQEBAQEBAQEBAQEBAAAAAAAAAAAAAAAAAAAAAAAAAAABAQEBAQEBAQEBAQEAAAAAAAAAAAAAAAAAAAAAAAAAAAEBAQEBAQEBAQEBAQAAAAAAAAAAAAAAAAAAAQEBAQEBAQEBAQEBAQEBAQEBAAAAAAAAAAAAAAAAAAABAQEBAQEBAQEBAQEBAQEBAQEAAAAAAAAAAAAAAAAAAAEBAQEBAQEBAQEBAQEBAQEBAQAAAAAAAAAAAAAAAAAAAQEBAQEBAQEBAQEBAQEBAQEBAAAAAAAAAAAAAAAAAAABAQEBAQEBAQEBAQEBAQEBAQEAAAAAAAAAAAAAAAAAAAEBAQEBAQEBAQEBAQ==" + }, + "palette" : { + "originalArgb8888" : [ -265674 ], + "convertedRgb565" : [ -122 ] } }, "diagnostics" : [ ] @@ -1176,14 +1176,14 @@ "last_modified" : 1774359772491, "fingerprint" : "eeb7cc665386299403b7be1c272375d5077f3647c587f8033aa8c9275f840562", "metadata" : { - "palette" : { - "originalArgb8888" : [ -265674 ], - "convertedRgb565" : [ -122 ] - }, "tile" : { "width" : 32, "height" : 32, "paletteIndices" : "AQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAAAAAAAAAAABAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEAAAAAAAAAAAEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQAAAAAAAAAAAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAAAAAAAAAAABAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEAAAAAAAAAAAEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQAAAAAAAAAAAQEBAQEBAQEBAQEBAAAAAAAAAAAAAAAAAAAAAAAAAAABAQEBAQEBAQEBAQEAAAAAAAAAAAAAAAAAAAAAAAAAAAEBAQEBAQEBAQEBAQAAAAAAAAAAAAAAAAAAAAAAAAAAAQEBAQEBAQEBAQEBAAAAAAAAAAAAAAAAAAAAAAAAAAABAQEBAQEBAQEBAQEAAAAAAAAAAAAAAAAAAAAAAAAAAAEBAQEBAQEBAQEBAQAAAAAAAAAAAAAAAAAAAAAAAAAAAQEBAQEBAQEBAQEBAAAAAAAAAAAAAAAAAAAAAAAAAAABAQEBAQEBAQEBAQEAAAAAAAAAAAAAAAAAAAAAAAAAAAEBAQEBAQEBAQEBAQAAAAAAAAAAAAAAAAAAAQEBAQEBAQEBAQEBAQEBAQEBAAAAAAAAAAAAAAAAAAABAQEBAQEBAQEBAQEBAQEBAQEAAAAAAAAAAAAAAAAAAAEBAQEBAQEBAQEBAQEBAQEBAQAAAAAAAAAAAAAAAAAAAQEBAQEBAQEBAQEBAAAAAAAAAAAAAAAAAAAAAAAAAAABAQEBAQEBAQEBAQEAAAAAAAAAAAAAAAAAAAAAAAAAAAEBAQEBAQEBAQEBAQAAAAAAAAAAAAAAAAAAAQEBAQEBAQEBAQEBAQEBAQEBAAAAAAAAAAAAAAAAAAABAQEBAQEBAQEBAQEBAQEBAQEAAAAAAAAAAAAAAAAAAAEBAQEBAQEBAQEBAQEBAQEBAQAAAAAAAAAAAAAAAAAAAQEBAQEBAQEBAQEBAQEBAQEBAAAAAAAAAAAAAAAAAAABAQEBAQEBAQEBAQEBAQEBAQEAAAAAAAAAAAAAAAAAAAEBAQEBAQEBAQEBAQ==" + }, + "palette" : { + "originalArgb8888" : [ -265674 ], + "convertedRgb565" : [ -122 ] } }, "diagnostics" : [ ] @@ -1194,14 +1194,14 @@ "last_modified" : 1774359772492, "fingerprint" : "eeb7cc665386299403b7be1c272375d5077f3647c587f8033aa8c9275f840562", "metadata" : { - "palette" : { - "originalArgb8888" : [ -265674 ], - "convertedRgb565" : [ -122 ] - }, "tile" : { "width" : 32, "height" : 32, "paletteIndices" : "AQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAAAAAAAAAAABAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEAAAAAAAAAAAEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQAAAAAAAAAAAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAAAAAAAAAAABAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEAAAAAAAAAAAEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQAAAAAAAAAAAQEBAQEBAQEBAQEBAAAAAAAAAAAAAAAAAAAAAAAAAAABAQEBAQEBAQEBAQEAAAAAAAAAAAAAAAAAAAAAAAAAAAEBAQEBAQEBAQEBAQAAAAAAAAAAAAAAAAAAAAAAAAAAAQEBAQEBAQEBAQEBAAAAAAAAAAAAAAAAAAAAAAAAAAABAQEBAQEBAQEBAQEAAAAAAAAAAAAAAAAAAAAAAAAAAAEBAQEBAQEBAQEBAQAAAAAAAAAAAAAAAAAAAAAAAAAAAQEBAQEBAQEBAQEBAAAAAAAAAAAAAAAAAAAAAAAAAAABAQEBAQEBAQEBAQEAAAAAAAAAAAAAAAAAAAAAAAAAAAEBAQEBAQEBAQEBAQAAAAAAAAAAAAAAAAAAAQEBAQEBAQEBAQEBAQEBAQEBAAAAAAAAAAAAAAAAAAABAQEBAQEBAQEBAQEBAQEBAQEAAAAAAAAAAAAAAAAAAAEBAQEBAQEBAQEBAQEBAQEBAQAAAAAAAAAAAAAAAAAAAQEBAQEBAQEBAQEBAAAAAAAAAAAAAAAAAAAAAAAAAAABAQEBAQEBAQEBAQEAAAAAAAAAAAAAAAAAAAAAAAAAAAEBAQEBAQEBAQEBAQAAAAAAAAAAAAAAAAAAAQEBAQEBAQEBAQEBAQEBAQEBAAAAAAAAAAAAAAAAAAABAQEBAQEBAQEBAQEBAQEBAQEAAAAAAAAAAAAAAAAAAAEBAQEBAQEBAQEBAQEBAQEBAQAAAAAAAAAAAAAAAAAAAQEBAQEBAQEBAQEBAQEBAQEBAAAAAAAAAAAAAAAAAAABAQEBAQEBAQEBAQEBAQEBAQEAAAAAAAAAAAAAAAAAAAEBAQEBAQEBAQEBAQ==" + }, + "palette" : { + "originalArgb8888" : [ -265674 ], + "convertedRgb565" : [ -122 ] } }, "diagnostics" : [ ] @@ -1212,14 +1212,14 @@ "last_modified" : 1774359772493, "fingerprint" : "eeb7cc665386299403b7be1c272375d5077f3647c587f8033aa8c9275f840562", "metadata" : { - "palette" : { - "originalArgb8888" : [ -265674 ], - "convertedRgb565" : [ -122 ] - }, "tile" : { "width" : 32, "height" : 32, "paletteIndices" : "AQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAAAAAAAAAAABAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEAAAAAAAAAAAEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQAAAAAAAAAAAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAAAAAAAAAAABAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEAAAAAAAAAAAEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQAAAAAAAAAAAQEBAQEBAQEBAQEBAAAAAAAAAAAAAAAAAAAAAAAAAAABAQEBAQEBAQEBAQEAAAAAAAAAAAAAAAAAAAAAAAAAAAEBAQEBAQEBAQEBAQAAAAAAAAAAAAAAAAAAAAAAAAAAAQEBAQEBAQEBAQEBAAAAAAAAAAAAAAAAAAAAAAAAAAABAQEBAQEBAQEBAQEAAAAAAAAAAAAAAAAAAAAAAAAAAAEBAQEBAQEBAQEBAQAAAAAAAAAAAAAAAAAAAAAAAAAAAQEBAQEBAQEBAQEBAAAAAAAAAAAAAAAAAAAAAAAAAAABAQEBAQEBAQEBAQEAAAAAAAAAAAAAAAAAAAAAAAAAAAEBAQEBAQEBAQEBAQAAAAAAAAAAAAAAAAAAAQEBAQEBAQEBAQEBAQEBAQEBAAAAAAAAAAAAAAAAAAABAQEBAQEBAQEBAQEBAQEBAQEAAAAAAAAAAAAAAAAAAAEBAQEBAQEBAQEBAQEBAQEBAQAAAAAAAAAAAAAAAAAAAQEBAQEBAQEBAQEBAAAAAAAAAAAAAAAAAAAAAAAAAAABAQEBAQEBAQEBAQEAAAAAAAAAAAAAAAAAAAAAAAAAAAEBAQEBAQEBAQEBAQAAAAAAAAAAAAAAAAAAAQEBAQEBAQEBAQEBAQEBAQEBAAAAAAAAAAAAAAAAAAABAQEBAQEBAQEBAQEBAQEBAQEAAAAAAAAAAAAAAAAAAAEBAQEBAQEBAQEBAQEBAQEBAQAAAAAAAAAAAAAAAAAAAQEBAQEBAQEBAQEBAQEBAQEBAAAAAAAAAAAAAAAAAAABAQEBAQEBAQEBAQEBAQEBAQEAAAAAAAAAAAAAAAAAAAEBAQEBAQEBAQEBAQ==" + }, + "palette" : { + "originalArgb8888" : [ -265674 ], + "convertedRgb565" : [ -122 ] } }, "diagnostics" : [ ] @@ -1230,14 +1230,14 @@ "last_modified" : 1774359772494, "fingerprint" : "eeb7cc665386299403b7be1c272375d5077f3647c587f8033aa8c9275f840562", "metadata" : { - "palette" : { - "originalArgb8888" : [ -265674 ], - "convertedRgb565" : [ -122 ] - }, "tile" : { "width" : 32, "height" : 32, "paletteIndices" : "AQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAAAAAAAAAAABAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEAAAAAAAAAAAEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQAAAAAAAAAAAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAAAAAAAAAAABAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEAAAAAAAAAAAEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQAAAAAAAAAAAQEBAQEBAQEBAQEBAAAAAAAAAAAAAAAAAAAAAAAAAAABAQEBAQEBAQEBAQEAAAAAAAAAAAAAAAAAAAAAAAAAAAEBAQEBAQEBAQEBAQAAAAAAAAAAAAAAAAAAAAAAAAAAAQEBAQEBAQEBAQEBAAAAAAAAAAAAAAAAAAAAAAAAAAABAQEBAQEBAQEBAQEAAAAAAAAAAAAAAAAAAAAAAAAAAAEBAQEBAQEBAQEBAQAAAAAAAAAAAAAAAAAAAAAAAAAAAQEBAQEBAQEBAQEBAAAAAAAAAAAAAAAAAAAAAAAAAAABAQEBAQEBAQEBAQEAAAAAAAAAAAAAAAAAAAAAAAAAAAEBAQEBAQEBAQEBAQAAAAAAAAAAAAAAAAAAAQEBAQEBAQEBAQEBAQEBAQEBAAAAAAAAAAAAAAAAAAABAQEBAQEBAQEBAQEBAQEBAQEAAAAAAAAAAAAAAAAAAAEBAQEBAQEBAQEBAQEBAQEBAQAAAAAAAAAAAAAAAAAAAQEBAQEBAQEBAQEBAAAAAAAAAAAAAAAAAAAAAAAAAAABAQEBAQEBAQEBAQEAAAAAAAAAAAAAAAAAAAAAAAAAAAEBAQEBAQEBAQEBAQAAAAAAAAAAAAAAAAAAAQEBAQEBAQEBAQEBAQEBAQEBAAAAAAAAAAAAAAAAAAABAQEBAQEBAQEBAQEBAQEBAQEAAAAAAAAAAAAAAAAAAAEBAQEBAQEBAQEBAQEBAQEBAQAAAAAAAAAAAAAAAAAAAQEBAQEBAQEBAQEBAQEBAQEBAAAAAAAAAAAAAAAAAAABAQEBAQEBAQEBAQEBAQEBAQEAAAAAAAAAAAAAAAAAAAEBAQEBAQEBAQEBAQ==" + }, + "palette" : { + "originalArgb8888" : [ -265674 ], + "convertedRgb565" : [ -122 ] } }, "diagnostics" : [ ] @@ -1248,14 +1248,14 @@ "last_modified" : 1774359772495, "fingerprint" : "eeb7cc665386299403b7be1c272375d5077f3647c587f8033aa8c9275f840562", "metadata" : { - "palette" : { - "originalArgb8888" : [ -265674 ], - "convertedRgb565" : [ -122 ] - }, "tile" : { "width" : 32, "height" : 32, "paletteIndices" : "AQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAAAAAAAAAAABAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEAAAAAAAAAAAEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQAAAAAAAAAAAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAAAAAAAAAAABAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEAAAAAAAAAAAEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQAAAAAAAAAAAQEBAQEBAQEBAQEBAAAAAAAAAAAAAAAAAAAAAAAAAAABAQEBAQEBAQEBAQEAAAAAAAAAAAAAAAAAAAAAAAAAAAEBAQEBAQEBAQEBAQAAAAAAAAAAAAAAAAAAAAAAAAAAAQEBAQEBAQEBAQEBAAAAAAAAAAAAAAAAAAAAAAAAAAABAQEBAQEBAQEBAQEAAAAAAAAAAAAAAAAAAAAAAAAAAAEBAQEBAQEBAQEBAQAAAAAAAAAAAAAAAAAAAAAAAAAAAQEBAQEBAQEBAQEBAAAAAAAAAAAAAAAAAAAAAAAAAAABAQEBAQEBAQEBAQEAAAAAAAAAAAAAAAAAAAAAAAAAAAEBAQEBAQEBAQEBAQAAAAAAAAAAAAAAAAAAAQEBAQEBAQEBAQEBAQEBAQEBAAAAAAAAAAAAAAAAAAABAQEBAQEBAQEBAQEBAQEBAQEAAAAAAAAAAAAAAAAAAAEBAQEBAQEBAQEBAQEBAQEBAQAAAAAAAAAAAAAAAAAAAQEBAQEBAQEBAQEBAAAAAAAAAAAAAAAAAAAAAAAAAAABAQEBAQEBAQEBAQEAAAAAAAAAAAAAAAAAAAAAAAAAAAEBAQEBAQEBAQEBAQAAAAAAAAAAAAAAAAAAAQEBAQEBAQEBAQEBAQEBAQEBAAAAAAAAAAAAAAAAAAABAQEBAQEBAQEBAQEBAQEBAQEAAAAAAAAAAAAAAAAAAAEBAQEBAQEBAQEBAQEBAQEBAQAAAAAAAAAAAAAAAAAAAQEBAQEBAQEBAQEBAQEBAQEBAAAAAAAAAAAAAAAAAAABAQEBAQEBAQEBAQEBAQEBAQEAAAAAAAAAAAAAAAAAAAEBAQEBAQEBAQEBAQ==" + }, + "palette" : { + "originalArgb8888" : [ -265674 ], + "convertedRgb565" : [ -122 ] } }, "diagnostics" : [ ] @@ -1266,14 +1266,14 @@ "last_modified" : 1775797786950, "fingerprint" : "0526996900bdeef23c72fe987fb45800f11895946dcd5f0f7f8390c879069a37", "metadata" : { - "palette" : { - "originalArgb8888" : [ -265674, -1736296, -13905598, -11518505, -14439577, -2467509 ], - "convertedRgb565" : [ -122, -7149, 11912, 20986, 9548, -9527 ] - }, "tile" : { "width" : 32, "height" : 32, "paletteIndices" : "AQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQECAgIBAQEBAQEBAQEBAQEBAQEBAwMDAwMDAQEBAQEBAgICAgICAgIBAQEBAQEBAQEBAQMDAwMDAwMBAQEBAQICAgICAgICAQEBAQEBAQEBAQEBAQMDAwMDAQEBAQEBAgICAgICAgEBAQEBAQQEBAQBAQEBAQEBAQEBAQEBAQEBAgICAgIBAQEBAQEEBAQEBAQBAQEBAQEBAQEBAQEBAQEBAgECAQEBAQEBAQQEBAQEAQEBAQEBAAAAAAAAAAABAQECAQEBAQEBAQEEBAQEBAEBAQEBAQEAAAAAAAAAAAEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQAAAAAAAAAAAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAAAAAAAAAAABAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEAAAAAAAAAAAEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQAAAAAAAAAAAQEBAQEBAQEBAQEBAAAAAAAAAAAAAAAAAAAAAAAAAAABAQEBAQEBAQEBAQEAAAAAAAAAAAAAAAAAAAAAAAAAAAEBAQEBAQEBAQEBAQAAAAAAAAAAAAAAAAAAAAAAAAAAAQEBAQEBAQUBAQEBAAAAAAAAAAAAAAAAAAAAAAAAAAABAQEBAQUFBQEBAQEAAAAAAAAAAAAAAAAAAAAAAAAAAAEBAQEFBQUFBQEBAQAAAAAAAAAAAAAAAAAAAAAAAAAAAQEBBQUFBQUBAQEBAAAAAAAAAAAAAAAAAAAAAAAAAAABAQEBBQUFAQEBAQEAAAAAAAAAAAAAAAAAAAAAAAAAAAEBAQEBAQEBAQEBAQAAAAAAAAAAAAAAAAAAAQEBAQEBAQEBAQEBAQEBAQEBAAAAAAAAAAAAAAAAAAABAQEBAQEBAQEBAQEBAQEBAQEAAAAAAAAAAAAAAAAAAAEBAQEBAQYGBgYBAQEBAQEBAQAAAAAAAAAAAAAAAAAAAQEBAQEBBgYGBgEBAAAAAAAAAAAAAAAAAAAAAAAAAAABAQEBAQEGBgYGAQEAAAAAAAAAAAAAAAAAAAAAAAAAAAEBAQEBAQYGBgYBAQAAAAAAAAAAAAAAAAAAAQEBAQEBAQEBAQEBAQYGAQEBAAAAAAAAAAAAAAAAAAABAQEBAQEBAQEBAQEBAQEBAQEAAAAAAAAAAAAAAAAAAAEBAQEBAQEBAQEBAQEBAQEBAQAAAAAAAAAAAAAAAAAAAQEBAQEBAQEBAQEBAQEBAQEBAAAAAAAAAAAAAAAAAAABAQEBAQEBAQEBAQEBAQEBAQEAAAAAAAAAAAAAAAAAAAEBAQEBAQEBAQEBAQ==" + }, + "palette" : { + "originalArgb8888" : [ -265674, -1736296, -13905598, -11518505, -14439577, -2467509 ], + "convertedRgb565" : [ -122, -7149, 11912, 20986, 9548, -9527 ] } }, "diagnostics" : [ ] @@ -1314,14 +1314,14 @@ "last_modified" : 1775797786770, "fingerprint" : "aa7d241deabcebe29a6096e14eaf16fdc06cf06380c11a507620b00fc7bff094", "metadata" : { - "palette" : { - "originalArgb8888" : [ -265674 ], - "convertedRgb565" : [ -122 ] - }, "tile" : { "width" : 16, "height" : 16, "paletteIndices" : "AQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAAAAAAEBAQEBAQEBAQEBAQAAAAABAQEBAQEBAQEBAQEAAAAAAQEBAQEBAAAAAAAAAAAAAAEBAQEBAQAAAAAAAAAAAAABAQEBAQEAAAAAAAAAAAAAAQEBAQEBAAAAAAAAAAAAAAEBAQEBAQAAAAAAAAABAQEBAQEBAQEAAAAAAAAAAQEBAQEBAAAAAAAAAAAAAAEBAQEBAQAAAAAAAAABAQEBAQEBAQEAAAAAAAAAAQEBAQEBAQEBAAAAAAAAAAEBAQEBAQ==" + }, + "palette" : { + "originalArgb8888" : [ -265674 ], + "convertedRgb565" : [ -122 ] } }, "diagnostics" : [ ] @@ -1344,14 +1344,14 @@ "last_modified" : 1775797786709, "fingerprint" : "6ca635a7906067b6a2a8460a8562718c445783e6df18b9f2c80c83c5ac569db6", "metadata" : { - "palette" : { - "originalArgb8888" : [ -130562, -14145496, -2043712, -460560, -13082456, -6252424, -10977088 ], - "convertedRgb565" : [ -2017, 10565, -6504, -34, 15125, -23345, 23576 ] - }, "tile" : { "width" : 32, "height" : 32, "paletteIndices" : "AQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQICAgICAgICAgAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAICAwMDAwMDAgAAAAAAAAAAAAACAgIAAAAAAAAAAAAAAAIEBQUFBQUDAgAAAAAAAgICAgMDAwIAAAAAAAAAAAAAAgQFAwYGBgUDAgICAgIDAwMDBQUFAwIAAAAAAAAAAAACBAUDBgYGBgUEBAQEAwUFBQUGAwMFBAICAAAAAAAAAAIEBQMGBgYGAwUFBwcFBgYGBgMDAwMFBAQCAgAAAAAAAgQFAwYGBgMDAwQEBAMGBgYGBgMDAwMHBwQDAgAAAAACBAUDBgYGAwMDAwQEAwYGBgYGAwMDBAQEBQUDAgIAAAIEBQMGBgYDAwMDBAQDBgYGBgYDAwMDBAQDAwUGAgAAAgQFAwYGBgMDAwMEBAMGBgYGBQUFBQUEBAUFBgIAAAACBAUDBgYGAwMDAwQEAwYGBQUGAwMDAwcHAwYCAAAAAAIEBQMFBQUFBQMDBAQDBgUGBgICAgICBAQCAgAAAAAAAgQFBQYGBgYDBQMEBAMFBgICAAAAAAACAgAAAAAAAAACBAMDBgICAgIDBQcHBQYCAAAAAAAAAAAAAAAAAAAAAgIDAwMCAAAAAAIEBAMDAgAAAAAAAAAAAAAAAAAAAAICAgICAgAAAAAAAAICAgIAAAAAAAAAAAAAAAAAAAAAAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQ==" + }, + "palette" : { + "originalArgb8888" : [ -130562, -14145496, -2043712, -460560, -13082456, -6252424, -10977088 ], + "convertedRgb565" : [ -2017, 10565, -6504, -34, 15125, -23345, 23576 ] } }, "diagnostics" : [ { @@ -1396,14 +1396,14 @@ "last_modified" : 1775797786706, "fingerprint" : "7feab8c868bb446afd3dd7250e70504fb0ca228f463650d2dd7c525144e0b321", "metadata" : { - "palette" : { - "originalArgb8888" : [ -16777216, -2109505, -526353, -395279, -130562, -13082456, -10911807, -6318217, -6186631, -6187143, -6318215, -13148249, -13016663, -14080215 ], - "convertedRgb565" : [ 0, -8585, -2115, -66, -2017, 15125, 23544, -25426, -23345, -23377, -25425, 13044, 15125, 10533 ] - }, "tile" : { "width" : 32, "height" : 32, "paletteIndices" : "AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAEBAQEBAQEAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAEBAgMDBAEBAQEBBQUFAAUFBQUFBQUBAQAAAAAAAAAAAAECBgcHBAIICAkBBQUFBQUFBQEBAQICAQEAAAAFBQAAAQIGAwMHBgYGBgIBBQUFBQEBCgIIBgYDBAEBBQUFAAABAgYDAwIJCQsJBgIBAQEBCAgMDA0JAgcHAwMBBQUAAAECBgMDAgsLCwsLBgMDAwIGBgkCCwILAgIHAwEFBQAAAQIGAwMCCQkJCQkCBgcHBgsLCwsCCwICAwMHAwEFAAABAgYDAgkJCQkJCQICAwMCCQkJAgkGBgYHBwcDDgUAAAECBwMCCQkJCQkJAgIDAgkJCQkGBgsCAwMDAwQEAQAAAQIHAwIJCQkJCQkCAgMCCQkJBgkLAQEBAQEBAQQBAAABAgcDAgkJCQkJAgICAwILCQYJAQEFBQUFBQUFAQEAAAECBwMCCQkJCQYGAgIDAgkGCwEFBQUFBQUFBQAAAAAAAQIHAwIJCQYGCQIGBgcMBgkBBQUFBQUFBQAAAAAAAAABAgcGBgYGCQsBAQIDBAIKAQUFBQUFBQAAAAAAAAAAAQECAwIJCQkBAQAAAQEBAQEAAAAAAAAAAAAAAAAAAAEBAQEBAQEBAQAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA==" + }, + "palette" : { + "originalArgb8888" : [ -16777216, -2109505, -526353, -395279, -130562, -13082456, -10911807, -6318217, -6186631, -6187143, -6318215, -13148249, -13016663, -14080215 ], + "convertedRgb565" : [ 0, -8585, -2115, -66, -2017, 15125, 23544, -25426, -23345, -23377, -25425, 13044, 15125, 10533 ] } }, "diagnostics" : [ ] @@ -1414,14 +1414,14 @@ "last_modified" : 1775797786710, "fingerprint" : "c363f3ef7f32d9b249c7dc8babdb3eb5aae68c524099e5e97290202b054dda71", "metadata" : { - "palette" : { - "originalArgb8888" : [ -14671840, -11431408, -9326048, -802016, -3964416, -5086944, -789517, -810399, -1863087, -10403552, -5078447 ], - "convertedRgb565" : [ 8452, 21634, 30084, -2556, -15360, -19708, -2146, -2804, -7030, 25092, -19446 ] - }, "tile" : { "width" : 32, "height" : 32, "paletteIndices" : "AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAABAQEBAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAEBAQICAwMBAQAAAAAAAAAAAAAAAAAAAAAAAAAAAAABBAQBAgIDAwMCAQAAAAAAAAAAAAAAAAAAAAAAAAAAAQUFBAQBAgIDAgICAQAAAAAAAAAAAAAAAAAAAAAAAAABBQEFBAUBAgICAgMBAAAAAAAAAAAAAAAAAAAAAAAAAAABBgEFBQUBAgECAgMBAAAAAAAAAAAAAAAAAAAAAAAAAAEGBwEFBAEBCAECAwEAAAAAAAAAAAAAAAAAAAAAAAAAAQgBBwEEAQgJAQICAQAAAAAAAAAAAAAAAAAAAAAAAAEICAEHAQQBCQYBAgIBAAAAAAAAAAAAAAAAAAAAAAAAAAEGCQkBBQEGAQUBAgEAAAAAAAAAAAAAAAAAAAAAAAAAAAEBBgYBBgEBAQABAAAAAAAAAAAAAAAAAAAAAAAAAAAAAQcBAQEBAgIBAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAECAwECAwIBAgEAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAQECAQcHBwECAQAAAAAAAAAAAAAAAAAAAAAAAAAAAAABBAEBAQEBAQECAQAAAAAAAAAAAAAAAAAAAAAAAAAAAAABAgEJCgoBAgEAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAQEBAQEJCQEBAQAAAAAAAAAAAAAAAAAAAAAAAAAAAAEBAQEKAQEBAQEBAQAAAAAAAAAAAAAAAAAAAAAAAAAAAQEBAQELCwoKAQEBAAAAAAAAAAAAAAAAAAAAAAAAAAAAAQEBAQEBAQEBAQAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAEBAQEBAQAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA==" + }, + "palette" : { + "originalArgb8888" : [ -14671840, -11431408, -9326048, -802016, -3964416, -5086944, -789517, -810399, -1863087, -10403552, -5078447 ], + "convertedRgb565" : [ 8452, 21634, 30084, -2556, -15360, -19708, -2146, -2804, -7030, 25092, -19446 ] } }, "diagnostics" : [ ] @@ -1432,14 +1432,14 @@ "last_modified" : 1775797786711, "fingerprint" : "e2130efbb9643b41a4fb62619f2713402f9622c7db040fe18d929609ef70b89a", "metadata" : { - "palette" : { - "originalArgb8888" : [ -14671840, -11431408, -9326048, -802016, -3964416, -5086944, -789517, -810399, -1863087, -10403552, -5078447 ], - "convertedRgb565" : [ 8452, 21634, 30084, -2556, -15360, -19708, -2146, -2804, -7030, 25092, -19446 ] - }, "tile" : { "width" : 32, "height" : 32, "paletteIndices" : "AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAQEBAQAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAABAQECAgMDAQEAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAQQEAQICAwMDAgEAAAAAAAAAAAAAAAAAAAAAAAAAAAEFBQQEAQICAwICAgEAAAAAAAAAAAAAAAAAAAAAAAAAAQUBBQQFAQICAgIDAQAAAAAAAAAAAAAAAAAAAAAAAAAAAQYBBQUFAQIBAgIDAQAAAAAAAAAAAAAAAAAAAAAAAAABBgcBBQQBAQgBAgMBAAAAAAAAAAAAAAAAAAAAAAAAAAEIAQcBBAEICQECAgEAAAAAAAAAAAAAAAAAAAAAAAABCAgBBwEEAQkGAQICAQAAAAAAAAAAAAAAAAAAAAAAAAABBgkJAQUBBgEFAQIBAAAAAAAAAAAAAAAAAAAAAAAAAAABAQYGAQYBAQEAAQAAAAAAAAAAAAAAAAAAAAAAAAAAAAEHAQEBAQECAQAAAAAAAAAAAAAAAAAAAAAAAAAAAAABAgEBBwMBAwMBAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAEBCQoBBwEDAgEBAAAAAAAAAAAAAAAAAAAAAAAAAAABAgEJCQoBAgIBAQIBAAAAAAAAAAAAAAAAAAAAAAAAAAECAgEBAQICAQECAQEAAAAAAAAAAAAAAAAAAAAAAAAAAAEBAgECAQECAgEBAQAAAAAAAAAAAAAAAAAAAAAAAAAAAQEBAQICAgEBAQoKAQAAAAAAAAAAAAAAAAAAAAAAAAEBAQEBAQEBAQELCwoBAAAAAAAAAAAAAAAAAAAAAAAAAQEBAQEBAQEBAQsLAQEAAAAAAAAAAAAAAAAAAAAAAAAAAQEBAQEBAQEBAQEBAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAEBAQEBAQAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA==" + }, + "palette" : { + "originalArgb8888" : [ -14671840, -11431408, -9326048, -802016, -3964416, -5086944, -789517, -810399, -1863087, -10403552, -5078447 ], + "convertedRgb565" : [ 8452, 21634, 30084, -2556, -15360, -19708, -2146, -2804, -7030, 25092, -19446 ] } }, "diagnostics" : [ ] @@ -1450,14 +1450,14 @@ "last_modified" : 1775797786713, "fingerprint" : "9216dfc6a6226fac398e9f781550d23fbfaa65bd377cdda69187149beca114ec", "metadata" : { - "palette" : { - "originalArgb8888" : [ -14671840, -11431408, -9326048, -802016, -3964416, -5086944, -789517, -810399, -1863087, -10403552, -5078447 ], - "convertedRgb565" : [ 8452, 21634, 30084, -2556, -15360, -19708, -2146, -2804, -7030, 25092, -19446 ] - }, "tile" : { "width" : 32, "height" : 32, "paletteIndices" : "AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAQEBAQAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAEBAQECAgMDAQEAAAEBAAAAAAAAAAAAAAAAAAAAAAABBAQEAQICAwMDAgEBAwEAAAAAAAAAAAAAAAAAAAAAAAEFBQQEAQICAwICAQIDAQAAAAAAAAAAAAAAAAAAAAAAAAEBBQQFAQICAgICAwEBAAAAAAAAAAAAAAAAAAAAAAAAAQYBBQUFAQIBAgICAQAAAAAAAAAAAAAAAAAAAAAAAAABBgcBBQQFAQgBAQEBAAAAAAAAAAAAAAAAAAAAAAAAAAEIAQcBBAUBCQEBBQUBAAAAAAAAAAAAAAAAAAAAAAABCAgBBwgBBAUBAQUBAAAAAAAAAAAAAAAAAAAAAAAAAAABBgkJBgYBAQEBAQAAAAAAAAAAAAAAAAAAAAAAAAAAAAABAQYGBgYBAQAAAAAAAAAAAAAAAAAAAAAAAAAAAAABAQEBAQEBAQMBAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAEJCgEHAwECAwEBAQAAAAAAAAAAAAAAAAAAAAAAAAABAQkKAQcCAQIDAQEBAQAAAAAAAAAAAAAAAAAAAAAAAAEKAQEBAQECAgEBAgELAQAAAAAAAAAAAAAAAAAAAAAAAQEKAQICAQEBAgIBAQoLAQAAAAAAAAAAAAAAAAAAAAAAAQEBAQECAgICAQEAAQEAAAAAAAAAAAAAAAAAAAAAAAAAAQEBAQEBAQEBAQAAAAAAAAAAAAAAAAAAAAAAAAAAAAEBAQEBAQEBAQEBAQAAAAAAAAAAAAAAAAAAAAAAAAAAAQEBAQEBAQEBAQEBAAAAAAAAAAAAAAAAAAAAAAAAAAAAAQEBAQEBAQEBAQAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAEBAQEBAQAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA==" + }, + "palette" : { + "originalArgb8888" : [ -14671840, -11431408, -9326048, -802016, -3964416, -5086944, -789517, -810399, -1863087, -10403552, -5078447 ], + "convertedRgb565" : [ 8452, 21634, 30084, -2556, -15360, -19708, -2146, -2804, -7030, 25092, -19446 ] } }, "diagnostics" : [ ] @@ -1468,14 +1468,14 @@ "last_modified" : 1775797786712, "fingerprint" : "ebc4b7ca7bb1455288681c5d71424f60f658a44cb343d0c3934329cec676c867", "metadata" : { - "palette" : { - "originalArgb8888" : [ -14671840, -11431408, -9326048, -802016, -3964416, -5086944, -789517, -810399, -1863087, -10403552, -5078447 ], - "convertedRgb565" : [ 8452, 21634, 30084, -2556, -15360, -19708, -2146, -2804, -7030, 25092, -19446 ] - }, "tile" : { "width" : 32, "height" : 32, "paletteIndices" : "AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAABAQEBAAAAAAEBAAAAAAAAAAAAAAAAAAAAAAAAAAEBAQICAwMBAQEBAwEAAAAAAAAAAAAAAAAAAAAAAAABBAQBAgIDAwMCAQMDAQAAAAAAAAAAAAAAAAAAAAAAAQUFBAQBAgIDAgICAwIBAAAAAAAAAAAAAAAAAAAAAAABBQEFBAUBAgICAgMCAQAAAAAAAAAAAAAAAAAAAAAAAAABBgEFBQUBAgECAgIBAAAAAAAAAAAAAAAAAAAAAAAAAAEGBwEFBAUBCAEBAQAAAAAAAAAAAAAAAAAAAAAAAAAAAQgBBwEEBQEJAQEAAAAAAAAAAAAAAAAAAAAAAAAAAAEICAEHCQEEBQEFAQAAAAAAAAAAAAAAAAAAAAAAAAAAAQEBCQkGBgEBAQUBAAAAAAAAAAAAAAAAAAAAAAAAAAABCQoBAQEGBgEBAQUBAAAAAAAAAAAAAAAAAAAAAAAAAAEKCgEHAgEBAQMBAQAAAAAAAAAAAAAAAAAAAAAAAAAAAAEBBwICAQIDAwEBAAAAAAAAAAAAAAAAAAAAAAAAAAABAQEBAQECAgMBAQIBAAAAAAAAAAAAAAAAAAAAAAAAAQoBAQIBAgICAgECAQEAAAAAAAAAAAAAAAAAAAAAAAABCgoBAgIBAQEBAgELAQAAAAAAAAAAAAAAAAAAAAAAAAEBAQEBAQICAgIBAQEAAAAAAAAAAAAAAAAAAAAAAAAAAAEBAQEBAQEBAQEBAQAAAAAAAAAAAAAAAAAAAAAAAAAAAQEBAQEBAQEBAQEBAAAAAAAAAAAAAAAAAAAAAAAAAAAAAQEBAQEBAQEBAQAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAEBAQEBAQAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA==" + }, + "palette" : { + "originalArgb8888" : [ -14671840, -11431408, -9326048, -802016, -3964416, -5086944, -789517, -810399, -1863087, -10403552, -5078447 ], + "convertedRgb565" : [ 8452, 21634, 30084, -2556, -15360, -19708, -2146, -2804, -7030, 25092, -19446 ] } }, "diagnostics" : [ ] @@ -1486,14 +1486,14 @@ "last_modified" : 1775797786718, "fingerprint" : "c363f3ef7f32d9b249c7dc8babdb3eb5aae68c524099e5e97290202b054dda71", "metadata" : { - "palette" : { - "originalArgb8888" : [ -14671840, -11431408, -9326048, -802016, -3964416, -5086944, -789517, -810399, -1863087, -10403552, -5078447 ], - "convertedRgb565" : [ 8452, 21634, 30084, -2556, -15360, -19708, -2146, -2804, -7030, 25092, -19446 ] - }, "tile" : { "width" : 32, "height" : 32, "paletteIndices" : "AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAABAQEBAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAEBAQICAwMBAQAAAAAAAAAAAAAAAAAAAAAAAAAAAAABBAQBAgIDAwMCAQAAAAAAAAAAAAAAAAAAAAAAAAAAAQUFBAQBAgIDAgICAQAAAAAAAAAAAAAAAAAAAAAAAAABBQEFBAUBAgICAgMBAAAAAAAAAAAAAAAAAAAAAAAAAAABBgEFBQUBAgECAgMBAAAAAAAAAAAAAAAAAAAAAAAAAAEGBwEFBAEBCAECAwEAAAAAAAAAAAAAAAAAAAAAAAAAAQgBBwEEAQgJAQICAQAAAAAAAAAAAAAAAAAAAAAAAAEICAEHAQQBCQYBAgIBAAAAAAAAAAAAAAAAAAAAAAAAAAEGCQkBBQEGAQUBAgEAAAAAAAAAAAAAAAAAAAAAAAAAAAEBBgYBBgEBAQABAAAAAAAAAAAAAAAAAAAAAAAAAAAAAQcBAQEBAgIBAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAECAwECAwIBAgEAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAQECAQcHBwECAQAAAAAAAAAAAAAAAAAAAAAAAAAAAAABBAEBAQEBAQECAQAAAAAAAAAAAAAAAAAAAAAAAAAAAAABAgEJCgoBAgEAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAQEBAQEJCQEBAQAAAAAAAAAAAAAAAAAAAAAAAAAAAAEBAQEKAQEBAQEBAQAAAAAAAAAAAAAAAAAAAAAAAAAAAQEBAQELCwoKAQEBAAAAAAAAAAAAAAAAAAAAAAAAAAAAAQEBAQEBAQEBAQAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAEBAQEBAQAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA==" + }, + "palette" : { + "originalArgb8888" : [ -14671840, -11431408, -9326048, -802016, -3964416, -5086944, -789517, -810399, -1863087, -10403552, -5078447 ], + "convertedRgb565" : [ 8452, 21634, 30084, -2556, -15360, -19708, -2146, -2804, -7030, 25092, -19446 ] } }, "diagnostics" : [ ] @@ -1504,14 +1504,14 @@ "last_modified" : 1775797786717, "fingerprint" : "1ba8ce75c445396334737143e0cfa56c87a1fb64cca8ad0962192594849249eb", "metadata" : { - "palette" : { - "originalArgb8888" : [ -14671840, -11431408, -9326048, -802016, -3964416, -5086944, -789517, -810399, -1863087, -10403552 ], - "convertedRgb565" : [ 8452, 21634, 30084, -2556, -15360, -19708, -2146, -2804, -7030, 25092 ] - }, "tile" : { "width" : 32, "height" : 32, "paletteIndices" : "AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAABAQEBAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAEBAQICAwMBAQAAAAAAAAAAAAAAAAAAAAAAAAAAAAABBAQBAgIDAwMCAQAAAAAAAAAAAAAAAAAAAAAAAAAAAQUFBAQBAgIDAgICAQAAAAAAAAAAAAAAAAAAAAAAAAABBQEFBAUBAgICAgMBAAAAAAAAAAAAAAAAAAAAAAAAAAABBgEFBQUBAgECAgMBAAAAAAAAAAAAAAAAAAAAAAAAAAEGBwEFBAEBCAECAwEAAAAAAAAAAAAAAAAAAAAAAAAAAQgBBwEEAQgJAQICAQAAAAAAAAAAAAAAAAAAAAAAAAEICAEHAQQBCQYBAgIBAAAAAAAAAAAAAAAAAAAAAAAAAAEGCQkBBQEGAQUBAgEAAAAAAAAAAAAAAAAAAAAAAAAAAAEBBgYBAQEBAQABAAAAAAAAAAAAAAAAAAAAAAAAAAAAAQcBAQEDAQEAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAABAwMBAgcHAQAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAQMDAwIBAQEBAQAAAAAAAAAAAAAAAAAAAAAAAAAAAAABBAIDAgEKCgECAQAAAAAAAAAAAAAAAAAAAAAAAAAAAAECAQEBAQkJAQIBAAAAAAAAAAAAAAAAAAAAAAAAAAAAAQECAgICAQECAQoBAAAAAAAAAAAAAAAAAAAAAAAAAAABAQEBAQICAgEKCgEAAAAAAAAAAAAAAAAAAAAAAAAAAQEBAQEBAQEBCgoKAQAAAAAAAAAAAAAAAAAAAAAAAAABAQEBAQEBAQEBAQEAAAAAAAAAAAAAAAAAAAAAAAAAAAABAQEBAQEBAQEBAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAQEBAQEBAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA==" + }, + "palette" : { + "originalArgb8888" : [ -14671840, -11431408, -9326048, -802016, -3964416, -5086944, -789517, -810399, -1863087, -10403552 ], + "convertedRgb565" : [ 8452, 21634, 30084, -2556, -15360, -19708, -2146, -2804, -7030, 25092 ] } }, "diagnostics" : [ ] @@ -1522,14 +1522,14 @@ "last_modified" : 1775797786714, "fingerprint" : "5e0954447699c6d5eac7550f1a10cf520efcddad0b9fbd9a716434da9d9550d4", "metadata" : { - "palette" : { - "originalArgb8888" : [ -14671840, -11431408, -9326048, -802016, -3964416, -5086944, -789517, -810399, -1863087, -10403552, -5078447 ], - "convertedRgb565" : [ 8452, 21634, 30084, -2556, -15360, -19708, -2146, -2804, -7030, 25092, -19446 ] - }, "tile" : { "width" : 32, "height" : 32, "paletteIndices" : "AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAABAQEBAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAQEBAQICAwMBAQAAAAAAAAAAAAAAAAAAAAAAAAAAAAEEBAQBAgIDAwMCAQABAQAAAAAAAAAAAAAAAAAAAAAAAQUFBAQBAgIDAgIBAQMBAAAAAAAAAAAAAAAAAAAAAAAAAQEFBAUBAgICAgIDAwEAAAAAAAAAAAAAAAAAAAAAAAABBgEFBQUBAgECAgIBAAAAAAAAAAAAAAAAAAAAAAAAAAEGBwEFBAUBCAEBAQEAAAAAAAAAAAAAAAAAAAAAAAAAAQgBBwEEBQEJAQEFBQEAAAAAAAAAAAAAAAAAAAAAAAEICAEHCAEEBQEBBQEBAAAAAAAAAAAAAAAAAAAAAAAAAAEGCQkGBgEBAQEBAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAEBBgYGAQIDAQAAAAAAAAAAAAAAAAAAAAAAAAAAAAABCQEBAQEBAQEHAQAAAAAAAAAAAAAAAAAAAAAAAAAAAQEBBwcDAgEKCgEBAAAAAAAAAAAAAAAAAAAAAAAAAAABAgIBAwMCAQkJAQEAAAAAAAAAAAAAAAAAAAAAAAAAAQEBAQIBAgMCAQEBCgEAAAAAAAAAAAAAAAAAAAAAAAABCwsKAQIBAQECAgEKAQAAAAAAAAAAAAAAAAAAAAAAAAABCwsKAQICAgIBCgoBAAAAAAAAAAAAAAAAAAAAAAAAAAABAQEBAQEBAQEBAQAAAAAAAAAAAAAAAAAAAAAAAAAAAQEBAQEBAQEBAQEBAAAAAAAAAAAAAAAAAAAAAAAAAAABAQEBAQEBAQEBAQEAAAAAAAAAAAAAAAAAAAAAAAAAAAABAQEBAQEBAQEBAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAQEBAQEBAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA==" + }, + "palette" : { + "originalArgb8888" : [ -14671840, -11431408, -9326048, -802016, -3964416, -5086944, -789517, -810399, -1863087, -10403552, -5078447 ], + "convertedRgb565" : [ 8452, 21634, 30084, -2556, -15360, -19708, -2146, -2804, -7030, 25092, -19446 ] } }, "diagnostics" : [ ] @@ -1540,14 +1540,14 @@ "last_modified" : 1775797786716, "fingerprint" : "6104ba7f216a937994d478ed07766ec28f48ad72fdd6620508535a1f877b8ddb", "metadata" : { - "palette" : { - "originalArgb8888" : [ -14671840, -11431408, -9326048, -802016, -3964416, -5086944, -789517, -810399, -1863087, -10403552, -5078447 ], - "convertedRgb565" : [ 8452, 21634, 30084, -2556, -15360, -19708, -2146, -2804, -7030, 25092, -19446 ] - }, "tile" : { "width" : 32, "height" : 32, "paletteIndices" : "AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAABAQEBAAAAAAEBAAAAAAAAAAAAAAAAAAAAAAAAAAEBAQICAwMBAQEBAwEAAAAAAAAAAAAAAAAAAAAAAAABBAQBAgIDAwMCAQMDAQAAAAAAAAAAAAAAAAAAAAAAAQUFBAQBAgIDAgICAwIBAAAAAAAAAAAAAAAAAAAAAAABBQEFBAUBAgICAgMCAQAAAAAAAAAAAAAAAAAAAAAAAAABBgEFBQUBAgECAgIBAAAAAAAAAAAAAAAAAAAAAAAAAAEGBwEFBAUBCAEBAQAAAAAAAAAAAAAAAAAAAAAAAAAAAQgBBwEEBQEJAQEAAAAAAAAAAAAAAAAAAAAAAAAAAAEICAEHCQEEBQEFAQAAAAAAAAAAAAAAAAAAAAAAAAAAAAEGCQkGBgEBAQEBAAAAAAAAAAAAAAAAAAAAAAAAAAABAQEBBgYGAQIDAgEBAAAAAAAAAAAAAAAAAAAAAAAAAAEJAQEBAQEBAgIBAQAAAAAAAAAAAAAAAAAAAAAAAAAAAAEBBwcDAgIBAQoKAQAAAAAAAAAAAAAAAAAAAAAAAAAAAQQBAwMDAgIBCQkBAAAAAAAAAAAAAAAAAAAAAAAAAAEBAgECAwMCAQEBAQEAAAAAAAAAAAAAAAAAAAAAAAABCwYBAgEBAQECAgEKAQAAAAAAAAAAAAAAAAAAAAAAAAELCgYBAgICAgEBAQEAAAAAAAAAAAAAAAAAAAAAAAAAAAEKCgoBAQEBAQEBAQAAAAAAAAAAAAAAAAAAAAAAAAAAAQEBAQEBAQEBAQEBAAAAAAAAAAAAAAAAAAAAAAAAAAAAAQEBAQEBAQEBAQAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAEBAQEBAQAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA==" + }, + "palette" : { + "originalArgb8888" : [ -14671840, -11431408, -9326048, -802016, -3964416, -5086944, -789517, -810399, -1863087, -10403552, -5078447 ], + "convertedRgb565" : [ 8452, 21634, 30084, -2556, -15360, -19708, -2146, -2804, -7030, 25092, -19446 ] } }, "diagnostics" : [ ] @@ -1602,14 +1602,14 @@ "last_modified" : 1776965154257, "fingerprint" : "8771c3e294d0edbc8dd3aaa6995a6db32166ae6bfb3e063170cc79b298d17e71", "metadata" : { - "palette" : { - "originalArgb8888" : [ -12019640 ], - "convertedRgb565" : [ 19657 ] - }, "tile" : { "width" : 8, "height" : 8, "paletteIndices" : "AQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQ==" + }, + "palette" : { + "originalArgb8888" : [ -12019640 ], + "convertedRgb565" : [ 19657 ] } }, "diagnostics" : [ ] @@ -1620,14 +1620,14 @@ "last_modified" : 1776965154257, "fingerprint" : "5d81eef8be13043330b42b546e10beed8ba00dfaa42df67477a8778c2b9484d7", "metadata" : { - "palette" : { - "originalArgb8888" : [ -12019640, -12552128, -14129088, -14133200, -14145496, -7835584, -5730208, -10465232 ], - "convertedRgb565" : [ 19657, 17352, 11080, 10950, 10565, -29816, -21364, 25222 ] - }, "tile" : { "width" : 8, "height" : 8, "paletteIndices" : "AQEBAQEBAQEBAQEBAQICAgECAgICAgICAgMEBQUFBQQDBAUGBgYGBQMEBQYGBwcIAwQFCAYGCAgBAwUFCAgIBw==" + }, + "palette" : { + "originalArgb8888" : [ -12019640, -12552128, -14129088, -14133200, -14145496, -7835584, -5730208, -10465232 ], + "convertedRgb565" : [ 19657, 17352, 11080, 10950, 10565, -29816, -21364, 25222 ] } }, "diagnostics" : [ ] @@ -1638,14 +1638,14 @@ "last_modified" : 1776965154258, "fingerprint" : "3250840c4fe08c134ea966ce7c8fcaccae2c2a45660d7173c5e262a2e5076548", "metadata" : { - "palette" : { - "originalArgb8888" : [ -12552128, -14133200, -14145496, -10465232, -5730208, -7835584 ], - "convertedRgb565" : [ 17352, 10950, 10565, 25222, -21364, -29816 ] - }, "tile" : { "width" : 8, "height" : 8, "paletteIndices" : "AQEBAQECAwMBAQEBAgMEBQEBAQIDBAUFAQIDAwQEBAQDAwYFBQUFBQQGBQUGBgYGBQUFBgYFBQUFBgYGBQUGBg==" + }, + "palette" : { + "originalArgb8888" : [ -12552128, -14133200, -14145496, -10465232, -5730208, -7835584 ], + "convertedRgb565" : [ 17352, 10950, 10565, 25222, -21364, -29816 ] } }, "diagnostics" : [ ] @@ -1656,14 +1656,14 @@ "last_modified" : 1776965154258, "fingerprint" : "fe3ab2b7eb3b10a042de14484d53e718e6b505edb1ad19053668565bfe3a8f25", "metadata" : { - "palette" : { - "originalArgb8888" : [ -14145496, -14133200, -12552128, -5730208, -10465232, -7835584 ], - "convertedRgb565" : [ 10565, 10950, 17352, -21364, 25222, -29816 ] - }, "tile" : { "width" : 8, "height" : 8, "paletteIndices" : "AQECAwMDAwMEBQECAwMDAwQEBQECAwMDBQUFBQEBAgMEBAQEBAYBAQYGBgYEBAYFBAQEBgYEBAQGBgQEBgYGBA==" + }, + "palette" : { + "originalArgb8888" : [ -14145496, -14133200, -12552128, -5730208, -10465232, -7835584 ], + "convertedRgb565" : [ 10565, 10950, 17352, -21364, 25222, -29816 ] } }, "diagnostics" : [ ] @@ -1674,14 +1674,14 @@ "last_modified" : 1776965154259, "fingerprint" : "7fcbf90e1e9a69d6ce3be80ea1901d66c9992f68dc72e4c636dcd2ad52fa2898", "metadata" : { - "palette" : { - "originalArgb8888" : [ -12019640, -12552128, -14133200, -14145496, -14129088, -7835584, -10465232, -5730208 ], - "convertedRgb565" : [ 19657, 17352, 10950, 10565, 11080, -29816, 25222, -21364 ] - }, "tile" : { "width" : 8, "height" : 8, "paletteIndices" : "AQEBAQEBAQECAgIBAQEBAQICAgICAgIBAwQEBAQDBQIEBgYGBgQDBQcICAYGBAMFBwcGBgcEAwUIBwcHBAQFAQ==" + }, + "palette" : { + "originalArgb8888" : [ -12019640, -12552128, -14133200, -14145496, -14129088, -7835584, -10465232, -5730208 ], + "convertedRgb565" : [ 19657, 17352, 10950, 10565, 11080, -29816, 25222, -21364 ] } }, "diagnostics" : [ ] @@ -1692,14 +1692,14 @@ "last_modified" : 1776965154259, "fingerprint" : "451fc8d646049944d5aa7c7dc254636eec0151aaff6e2051059304b9d6ebc31e", "metadata" : { - "palette" : { - "originalArgb8888" : [ -12019640, -14129088, -14133200, -14145496, -10465232, -5730208, -7835584 ], - "convertedRgb565" : [ 19657, 11080, 10950, 10565, 25222, -21364, -29816 ] - }, "tile" : { "width" : 8, "height" : 8, "paletteIndices" : "AQIDBAQFBgYBAQIDBAYGBwEBAQMEBgcHAQEBBAQGBwcBAQQFBAYHBwEEBwUEBgcHBAcGBQQGBwcEBwYFBAYHBw==" + }, + "palette" : { + "originalArgb8888" : [ -12019640, -14129088, -14133200, -14145496, -10465232, -5730208, -7835584 ], + "convertedRgb565" : [ 19657, 11080, 10950, 10565, 25222, -21364, -29816 ] } }, "diagnostics" : [ ] @@ -1710,14 +1710,14 @@ "last_modified" : 1776965154260, "fingerprint" : "aa757df4600823ec6655235a1081061777124ccee74b31481bbe402e53635f53", "metadata" : { - "palette" : { - "originalArgb8888" : [ -7835584, -5730208, -10465232, -14145496 ], - "convertedRgb565" : [ -29816, -21364, 25222, 10565 ] - }, "tile" : { "width" : 8, "height" : 8, "paletteIndices" : "AQECAwMBAQEBAgIBAwMBAgICAQEBAwMCAgIBAQIDBAMCAgEBAgMEBAICAQECAwQEAgIBAQIDBAMCAgIBAwQDAg==" + }, + "palette" : { + "originalArgb8888" : [ -7835584, -5730208, -10465232, -14145496 ], + "convertedRgb565" : [ -29816, -21364, 25222, 10565 ] } }, "diagnostics" : [ ] @@ -1728,14 +1728,14 @@ "last_modified" : 1776965154260, "fingerprint" : "38162157f5685cce25b835d3a2caee3465fd2ec3ee5db2a5089d7d5ae5ea3bb7", "metadata" : { - "palette" : { - "originalArgb8888" : [ -7835584, -10465232, -5730208, -14145496 ], - "convertedRgb565" : [ -29816, 25222, -21364, 10565 ] - }, "tile" : { "width" : 8, "height" : 8, "paletteIndices" : "AQEBAgIDAQEDAQICAQMDAQMCAgEBAQMDAgQCAwEBAwMEBAIDAQEDAwQEAgMBAQMDAgQCAwEBAwMDAgQCAQMDAw==" + }, + "palette" : { + "originalArgb8888" : [ -7835584, -10465232, -5730208, -14145496 ], + "convertedRgb565" : [ -29816, 25222, -21364, 10565 ] } }, "diagnostics" : [ ] @@ -1746,14 +1746,14 @@ "last_modified" : 1776965154260, "fingerprint" : "8cab5b3d553af9ed371bd19fc624763accc90e5d926d300ba31dd8d9d6bab803", "metadata" : { - "palette" : { - "originalArgb8888" : [ -5730208, -10465232, -14145496, -14133200, -14129088, -12019640, -7835584 ], - "convertedRgb565" : [ -21364, 25222, 10565, 10950, 11080, 19657, -29816 ] - }, "tile" : { "width" : 8, "height" : 8, "paletteIndices" : "AQECAwMEBQYHAQEDBAUGBgcHAQMEBgYGBwcBAwMGBgYHBwEDAgMGBgcHAQMCBwMGBwcBAwIBBwMHBwEDAgEHAw==" + }, + "palette" : { + "originalArgb8888" : [ -5730208, -10465232, -14145496, -14133200, -14129088, -12019640, -7835584 ], + "convertedRgb565" : [ -21364, 25222, 10565, 10950, 11080, 19657, -29816 ] } }, "diagnostics" : [ ] @@ -1764,14 +1764,14 @@ "last_modified" : 1776965154261, "fingerprint" : "d9ff5a6df0f65f5fcfb8f22376beeb266d429e2c6e9c82f51c12bc6ee4c3fcdc", "metadata" : { - "palette" : { - "originalArgb8888" : [ -14145496, -10465232, -7835584, -5730208, -14133200, -14129088, -12019640 ], - "convertedRgb565" : [ 10565, 25222, -29816, -21364, 10950, 11080, 19657 ] - }, "tile" : { "width" : 8, "height" : 8, "paletteIndices" : "AQIDAgIBBAMFAQECAgEEBAUGBQECAgEEBwYFBQECAQEHBwYGBQEBAgcHBwYFAQMDBwcHBwEBAwMHBwcFAQICAw==" + }, + "palette" : { + "originalArgb8888" : [ -14145496, -10465232, -7835584, -5730208, -14133200, -14129088, -12019640 ], + "convertedRgb565" : [ 10565, 25222, -29816, -21364, 10950, 11080, 19657 ] } }, "diagnostics" : [ ] @@ -1782,14 +1782,14 @@ "last_modified" : 1776965154261, "fingerprint" : "b9ff45c77f7779a6acebcc537c2ddac0e27e91162b656a04dc4772ec5f24fc26", "metadata" : { - "palette" : { - "originalArgb8888" : [ -7835584, -5730208, -10465232, -14145496 ], - "convertedRgb565" : [ -29816, -21364, 25222, 10565 ] - }, "tile" : { "width" : 8, "height" : 8, "paletteIndices" : "AQICAwMBAQIBAQMDAgIBAQIBAQEBAgIBAgICAgEBAgIEAwMCAgEBAQMEAwMCAgEBAQMEAwMDAgIBAwMEAwMDAw==" + }, + "palette" : { + "originalArgb8888" : [ -7835584, -5730208, -10465232, -14145496 ], + "convertedRgb565" : [ -29816, -21364, 25222, 10565 ] } }, "diagnostics" : [ ] @@ -1800,14 +1800,14 @@ "last_modified" : 1776965154261, "fingerprint" : "43f370324fedccda888d49409e2a64f182f08b4143b4bdd5bafaf498feebd21a", "metadata" : { - "palette" : { - "originalArgb8888" : [ -5730208, -7835584, -10465232, -14145496 ], - "convertedRgb565" : [ -21364, -29816, 25222, 10565 ] - }, "tile" : { "width" : 8, "height" : 8, "paletteIndices" : "AQICAwMBAQICAgEBAwMCAgIBAQICAgIBAQECAgEBAQECAgIBAQMDBAICAQEDAwQDAQEDAwMEAwIDAwMDBAMDAg==" + }, + "palette" : { + "originalArgb8888" : [ -5730208, -7835584, -10465232, -14145496 ], + "convertedRgb565" : [ -21364, -29816, 25222, 10565 ] } }, "diagnostics" : [ ] @@ -1818,14 +1818,14 @@ "last_modified" : 1776965154262, "fingerprint" : "cb047e655f4e196f22ca0048149df5dcb959f895faeaeb94920182d4a2d16b38", "metadata" : { - "palette" : { - "originalArgb8888" : [ -7835584, -5730208, -14145496, -10465232, -14133200, -14129088, -12019640 ], - "convertedRgb565" : [ -29816, -21364, 10565, 25222, 10950, 11080, 19657 ] - }, "tile" : { "width" : 8, "height" : 8, "paletteIndices" : "AQIDBAQBBAMCAgMEBAMDBQIDBAQDBQYFAwMEAwUFBgcEAwMFBgYHBwEBAwUGBwcHAQEDAwcHBwcBBAQDBQcHBw==" + }, + "palette" : { + "originalArgb8888" : [ -7835584, -5730208, -14145496, -10465232, -14133200, -14129088, -12019640 ], + "convertedRgb565" : [ -29816, -21364, 10565, 25222, 10950, 11080, 19657 ] } }, "diagnostics" : [ ] @@ -1836,14 +1836,14 @@ "last_modified" : 1776965154262, "fingerprint" : "25eba17b67dd5159f5fb9d3edd531d54a44d1c76f997385840dac53517b98886", "metadata" : { - "palette" : { - "originalArgb8888" : [ -12019640, -14145496, -7835584, -10465232, -14133200, -14129088 ], - "convertedRgb565" : [ 19657, 10565, -29816, 25222, 10950, 11080 ] - }, "tile" : { "width" : 8, "height" : 8, "paletteIndices" : "AQEBAgMDBAQBAQIDAwMDBAEBAgMDAwMEAQECAwMEAgQBAQIEAgUFAgEBBQUGBQYFAQEBAQEGAQYBAQEBAQEBAQ==" + }, + "palette" : { + "originalArgb8888" : [ -12019640, -14145496, -7835584, -10465232, -14133200, -14129088 ], + "convertedRgb565" : [ 19657, 10565, -29816, 25222, 10950, 11080 ] } }, "diagnostics" : [ ] @@ -1854,14 +1854,14 @@ "last_modified" : 1776965154262, "fingerprint" : "32ca96c14290de8009fd2db623f55514bed2345b7d5881a80dd3fe6235012854", "metadata" : { - "palette" : { - "originalArgb8888" : [ -10465232, -14145496, -14133200, -7835584, -14129088, -12019640 ], - "convertedRgb565" : [ 25222, 10565, 10950, -29816, 11080, 19657 ] - }, "tile" : { "width" : 8, "height" : 8, "paletteIndices" : "AQEBAgEBAgICAQICAQIBAQICAwICAQEEAgMDAwIBAQQDAwUDAwIBAQUFBgUFAgEEBgYGBgYDAgEGBgYGBgYDAg==" + }, + "palette" : { + "originalArgb8888" : [ -10465232, -14145496, -14133200, -7835584, -14129088, -12019640 ], + "convertedRgb565" : [ 25222, 10565, 10950, -29816, 11080, 19657 ] } }, "diagnostics" : [ ] @@ -1872,14 +1872,14 @@ "last_modified" : 1776965154263, "fingerprint" : "7a093fe00c805bcf38d4facff14a6d4c2b8baeaa2d553fa8d3db9f2d76b32f3b", "metadata" : { - "palette" : { - "originalArgb8888" : [ -14145496, -10465232, -7835584, -14133200, -14129088, -12019640 ], - "convertedRgb565" : [ 10565, 25222, -29816, 10950, 11080, 19657 ] - }, "tile" : { "width" : 8, "height" : 8, "paletteIndices" : "AQECAgECAgICAgECAQECAQMCAgEBBAEBAwICAQQEBAECAgEEBAUEBAMCAQUFBgUFAgEEBgYGBgYBBAYGBgYGBg==" + }, + "palette" : { + "originalArgb8888" : [ -14145496, -10465232, -7835584, -14133200, -14129088, -12019640 ], + "convertedRgb565" : [ 10565, 25222, -29816, 10950, 11080, 19657 ] } }, "diagnostics" : [ ] @@ -1890,14 +1890,14 @@ "last_modified" : 1776965154263, "fingerprint" : "77c5277220421226d16f58b1bcfb4eaf157fa4f6c740c5aaebefaf88fb91c22e", "metadata" : { - "palette" : { - "originalArgb8888" : [ -10465232, -7835584, -14145496, -12019640, -14133200, -14129088 ], - "convertedRgb565" : [ 25222, -29816, 10565, 19657, 10950, 11080 ] - }, "tile" : { "width" : 8, "height" : 8, "paletteIndices" : "AQECAgMEBAQBAgICAgMEBAECAgICAwQEAQMBAgIDBAQDBQUDAQMEBAUGBQYFBQQEBgQGBAQEBAQEBAQEBAQEBA==" + }, + "palette" : { + "originalArgb8888" : [ -10465232, -7835584, -14145496, -12019640, -14133200, -14129088 ], + "convertedRgb565" : [ 25222, -29816, 10565, 19657, 10950, 11080 ] } }, "diagnostics" : [ ] -- 2.47.2 From 7415b70d1ba3d6a2e40cbb149359f8a4fda5ce85 Mon Sep 17 00:00:00 2001 From: bQUARKz Date: Wed, 6 May 2026 00:21:41 +0100 Subject: [PATCH 10/37] package moving --- .../src/main/java/p/studio/AppContainer.java | 13 ++++++------ .../p/studio/lsp/api/LspServerLifecycle.java | 4 ++++ .../{api => messages}/LspProjectContext.java | 2 +- .../LspServerBootRequest.java | 2 +- .../LspServerConfiguration.java | 2 +- .../{api => messages}/LspServerEndpoint.java | 2 +- .../{api => messages}/LspServerHandle.java | 2 +- .../lsp/api/LspServerBootRequestTest.java | 3 +++ .../BaselineDocumentAnalysis.java | 2 +- .../BaselineDocumentIssue.java | 2 +- .../compiler => messages}/BaselineHover.java | 2 +- .../BaselineIssueSeverity.java | 2 +- .../BaselineServerDescription.java | 2 +- .../LanguageServiceBridge.java | 7 +++++-- .../LspServerLifecycle.java} | 19 +++++++++--------- .../CompilerLanguageServiceBridge.java | 5 +++-- .../host/ProjectScopedLspServerHost.java | 4 ++-- .../ProjectScopedLspServerHostFactory.java | 6 +++--- .../host/TcpLspServerHost.java | 10 +++++----- .../host/TcpLspServerHostFactory.java | 6 +++--- .../protocol/ProjectConnectionValidator.java | 4 ++-- .../protocol/PrometeuLanguageServer.java | 19 ++++++++++-------- .../protocol/PrometeuTextDocumentService.java | 8 ++++---- .../protocol/PrometeuWorkspaceService.java | 2 +- .../mapping/Lsp4jProtocolMessageMapper.java | 4 ++-- .../mapping/ProtocolMessageMapper.java | 8 ++++---- .../LspServerLifecycleTest.java} | 20 +++++++++---------- .../boundary/LspV1BoundaryTest.java | 6 +++--- .../CompilerLanguageServiceBridgeTest.java | 7 +++++-- .../protocol/PrometeuLanguageServerTest.java | 12 ++++++----- .../PrometeuTextDocumentServiceTest.java | 8 ++++---- .../projectsessions/StudioProjectSession.java | 4 ++-- .../StudioProjectSessionFactory.java | 6 +++--- .../StudioProjectSessionFactoryTest.java | 9 +++++---- .../StudioProjectSessionTest.java | 10 ++++++---- 35 files changed, 122 insertions(+), 102 deletions(-) rename prometeu-lsp/prometeu-lsp-api/src/main/java/p/studio/lsp/{api => messages}/LspProjectContext.java (96%) rename prometeu-lsp/prometeu-lsp-api/src/main/java/p/studio/lsp/{api => messages}/LspServerBootRequest.java (94%) rename prometeu-lsp/prometeu-lsp-api/src/main/java/p/studio/lsp/{api => messages}/LspServerConfiguration.java (96%) rename prometeu-lsp/prometeu-lsp-api/src/main/java/p/studio/lsp/{api => messages}/LspServerEndpoint.java (94%) rename prometeu-lsp/prometeu-lsp-api/src/main/java/p/studio/lsp/{api => messages}/LspServerHandle.java (90%) rename prometeu-lsp/prometeu-lsp-v1/src/main/java/p/studio/lsp/{v1/compiler => messages}/BaselineDocumentAnalysis.java (88%) rename prometeu-lsp/prometeu-lsp-v1/src/main/java/p/studio/lsp/{v1/compiler => messages}/BaselineDocumentIssue.java (95%) rename prometeu-lsp/prometeu-lsp-v1/src/main/java/p/studio/lsp/{v1/compiler => messages}/BaselineHover.java (91%) rename prometeu-lsp/prometeu-lsp-v1/src/main/java/p/studio/lsp/{v1/compiler => messages}/BaselineIssueSeverity.java (69%) rename prometeu-lsp/prometeu-lsp-v1/src/main/java/p/studio/lsp/{v1/compiler => messages}/BaselineServerDescription.java (94%) rename prometeu-lsp/prometeu-lsp-v1/src/main/java/p/studio/lsp/{v1/compiler => services}/LanguageServiceBridge.java (62%) rename prometeu-lsp/prometeu-lsp-v1/src/main/java/p/studio/lsp/{v1/bootstrap/LspV1ServerLifecycle.java => services/LspServerLifecycle.java} (82%) rename prometeu-lsp/prometeu-lsp-v1/src/main/java/p/studio/lsp/{v1 => services}/compiler/CompilerLanguageServiceBridge.java (95%) rename prometeu-lsp/prometeu-lsp-v1/src/main/java/p/studio/lsp/{v1 => services}/host/ProjectScopedLspServerHost.java (64%) rename prometeu-lsp/prometeu-lsp-v1/src/main/java/p/studio/lsp/{v1 => services}/host/ProjectScopedLspServerHostFactory.java (55%) rename prometeu-lsp/prometeu-lsp-v1/src/main/java/p/studio/lsp/{v1 => services}/host/TcpLspServerHost.java (93%) rename prometeu-lsp/prometeu-lsp-v1/src/main/java/p/studio/lsp/{v1 => services}/host/TcpLspServerHostFactory.java (68%) rename prometeu-lsp/prometeu-lsp-v1/src/main/java/p/studio/lsp/{v1 => services}/protocol/ProjectConnectionValidator.java (97%) rename prometeu-lsp/prometeu-lsp-v1/src/main/java/p/studio/lsp/{v1 => services}/protocol/PrometeuLanguageServer.java (85%) rename prometeu-lsp/prometeu-lsp-v1/src/main/java/p/studio/lsp/{v1 => services}/protocol/PrometeuTextDocumentService.java (93%) rename prometeu-lsp/prometeu-lsp-v1/src/main/java/p/studio/lsp/{v1 => services}/protocol/PrometeuWorkspaceService.java (91%) rename prometeu-lsp/prometeu-lsp-v1/src/main/java/p/studio/lsp/{v1 => services}/protocol/mapping/Lsp4jProtocolMessageMapper.java (97%) rename prometeu-lsp/prometeu-lsp-v1/src/main/java/p/studio/lsp/{v1 => services}/protocol/mapping/ProtocolMessageMapper.java (74%) rename prometeu-lsp/prometeu-lsp-v1/src/test/java/p/studio/lsp/{v1/bootstrap/LspV1ServerLifecycleTest.java => services/LspServerLifecycleTest.java} (73%) rename prometeu-lsp/prometeu-lsp-v1/src/test/java/p/studio/lsp/{v1 => services}/boundary/LspV1BoundaryTest.java (86%) rename prometeu-lsp/prometeu-lsp-v1/src/test/java/p/studio/lsp/{v1 => services}/compiler/CompilerLanguageServiceBridgeTest.java (82%) rename prometeu-lsp/prometeu-lsp-v1/src/test/java/p/studio/lsp/{v1 => services}/protocol/PrometeuLanguageServerTest.java (94%) rename prometeu-lsp/prometeu-lsp-v1/src/test/java/p/studio/lsp/{v1 => services}/protocol/PrometeuTextDocumentServiceTest.java (96%) diff --git a/prometeu-app/src/main/java/p/studio/AppContainer.java b/prometeu-app/src/main/java/p/studio/AppContainer.java index 8bcaeb8f..6f84a69d 100644 --- a/prometeu-app/src/main/java/p/studio/AppContainer.java +++ b/prometeu-app/src/main/java/p/studio/AppContainer.java @@ -2,12 +2,11 @@ package p.studio; import com.fasterxml.jackson.databind.ObjectMapper; import p.packer.Packer; -import p.studio.lsp.api.LspServerLifecycle; import p.studio.lsp.events.StudioEventBus; import p.studio.lsp.events.StudioPackerEventAdapter; -import p.studio.lsp.v1.bootstrap.LspV1ServerLifecycle; -import p.studio.lsp.v1.compiler.CompilerLanguageServiceBridge; -import p.studio.lsp.v1.host.TcpLspServerHostFactory; +import p.studio.lsp.services.LspServerLifecycle; +import p.studio.lsp.services.compiler.CompilerLanguageServiceBridge; +import p.studio.lsp.services.host.TcpLspServerHostFactory; import p.studio.utilities.ThemeService; import p.studio.utilities.i18n.I18nService; @@ -23,7 +22,7 @@ public final class AppContainer implements Container { private final ObjectMapper mapper; private final EmbeddedPacker embeddedPacker; private final StudioBackgroundTasks backgroundTasks; - private final LspServerLifecycle lspServerLifecycle; + private final p.studio.lsp.api.LspServerLifecycle lspServerLifecycle; public AppContainer() { this.i18nService = new I18nService(); @@ -34,7 +33,7 @@ public final class AppContainer implements Container { this.backgroundTasks = new StudioBackgroundTasks(backgroundExecutor); final Packer packer = Packer.bootstrap(this.mapper, new StudioPackerEventAdapter(studioEventBus)); this.embeddedPacker = new EmbeddedPacker(packer.workspaceService(), packer::close); - this.lspServerLifecycle = new LspV1ServerLifecycle( + this.lspServerLifecycle = new LspServerLifecycle( new TcpLspServerHostFactory(), new CompilerLanguageServiceBridge()); } @@ -70,7 +69,7 @@ public final class AppContainer implements Container { } @Override - public LspServerLifecycle getLspServerLifecycle() { + public p.studio.lsp.api.LspServerLifecycle getLspServerLifecycle() { return lspServerLifecycle; } diff --git a/prometeu-lsp/prometeu-lsp-api/src/main/java/p/studio/lsp/api/LspServerLifecycle.java b/prometeu-lsp/prometeu-lsp-api/src/main/java/p/studio/lsp/api/LspServerLifecycle.java index 24863daa..749733de 100644 --- a/prometeu-lsp/prometeu-lsp-api/src/main/java/p/studio/lsp/api/LspServerLifecycle.java +++ b/prometeu-lsp/prometeu-lsp-api/src/main/java/p/studio/lsp/api/LspServerLifecycle.java @@ -1,5 +1,9 @@ package p.studio.lsp.api; +import p.studio.lsp.messages.LspProjectContext; +import p.studio.lsp.messages.LspServerBootRequest; +import p.studio.lsp.messages.LspServerHandle; + public interface LspServerLifecycle { LspServerHandle bootServer(LspServerBootRequest request); diff --git a/prometeu-lsp/prometeu-lsp-api/src/main/java/p/studio/lsp/api/LspProjectContext.java b/prometeu-lsp/prometeu-lsp-api/src/main/java/p/studio/lsp/messages/LspProjectContext.java similarity index 96% rename from prometeu-lsp/prometeu-lsp-api/src/main/java/p/studio/lsp/api/LspProjectContext.java rename to prometeu-lsp/prometeu-lsp-api/src/main/java/p/studio/lsp/messages/LspProjectContext.java index 02b9f8da..aa9dfcb9 100644 --- a/prometeu-lsp/prometeu-lsp-api/src/main/java/p/studio/lsp/api/LspProjectContext.java +++ b/prometeu-lsp/prometeu-lsp-api/src/main/java/p/studio/lsp/messages/LspProjectContext.java @@ -1,4 +1,4 @@ -package p.studio.lsp.api; +package p.studio.lsp.messages; import java.nio.file.Path; import java.util.Objects; diff --git a/prometeu-lsp/prometeu-lsp-api/src/main/java/p/studio/lsp/api/LspServerBootRequest.java b/prometeu-lsp/prometeu-lsp-api/src/main/java/p/studio/lsp/messages/LspServerBootRequest.java similarity index 94% rename from prometeu-lsp/prometeu-lsp-api/src/main/java/p/studio/lsp/api/LspServerBootRequest.java rename to prometeu-lsp/prometeu-lsp-api/src/main/java/p/studio/lsp/messages/LspServerBootRequest.java index 2406a24f..ba3e057d 100644 --- a/prometeu-lsp/prometeu-lsp-api/src/main/java/p/studio/lsp/api/LspServerBootRequest.java +++ b/prometeu-lsp/prometeu-lsp-api/src/main/java/p/studio/lsp/messages/LspServerBootRequest.java @@ -1,4 +1,4 @@ -package p.studio.lsp.api; +package p.studio.lsp.messages; import java.util.Objects; diff --git a/prometeu-lsp/prometeu-lsp-api/src/main/java/p/studio/lsp/api/LspServerConfiguration.java b/prometeu-lsp/prometeu-lsp-api/src/main/java/p/studio/lsp/messages/LspServerConfiguration.java similarity index 96% rename from prometeu-lsp/prometeu-lsp-api/src/main/java/p/studio/lsp/api/LspServerConfiguration.java rename to prometeu-lsp/prometeu-lsp-api/src/main/java/p/studio/lsp/messages/LspServerConfiguration.java index f5f8644a..1307584f 100644 --- a/prometeu-lsp/prometeu-lsp-api/src/main/java/p/studio/lsp/api/LspServerConfiguration.java +++ b/prometeu-lsp/prometeu-lsp-api/src/main/java/p/studio/lsp/messages/LspServerConfiguration.java @@ -1,4 +1,4 @@ -package p.studio.lsp.api; +package p.studio.lsp.messages; import java.util.Objects; diff --git a/prometeu-lsp/prometeu-lsp-api/src/main/java/p/studio/lsp/api/LspServerEndpoint.java b/prometeu-lsp/prometeu-lsp-api/src/main/java/p/studio/lsp/messages/LspServerEndpoint.java similarity index 94% rename from prometeu-lsp/prometeu-lsp-api/src/main/java/p/studio/lsp/api/LspServerEndpoint.java rename to prometeu-lsp/prometeu-lsp-api/src/main/java/p/studio/lsp/messages/LspServerEndpoint.java index db255c1f..d8bdebed 100644 --- a/prometeu-lsp/prometeu-lsp-api/src/main/java/p/studio/lsp/api/LspServerEndpoint.java +++ b/prometeu-lsp/prometeu-lsp-api/src/main/java/p/studio/lsp/messages/LspServerEndpoint.java @@ -1,4 +1,4 @@ -package p.studio.lsp.api; +package p.studio.lsp.messages; import java.util.Objects; diff --git a/prometeu-lsp/prometeu-lsp-api/src/main/java/p/studio/lsp/api/LspServerHandle.java b/prometeu-lsp/prometeu-lsp-api/src/main/java/p/studio/lsp/messages/LspServerHandle.java similarity index 90% rename from prometeu-lsp/prometeu-lsp-api/src/main/java/p/studio/lsp/api/LspServerHandle.java rename to prometeu-lsp/prometeu-lsp-api/src/main/java/p/studio/lsp/messages/LspServerHandle.java index 9c90d38f..b894435c 100644 --- a/prometeu-lsp/prometeu-lsp-api/src/main/java/p/studio/lsp/api/LspServerHandle.java +++ b/prometeu-lsp/prometeu-lsp-api/src/main/java/p/studio/lsp/messages/LspServerHandle.java @@ -1,4 +1,4 @@ -package p.studio.lsp.api; +package p.studio.lsp.messages; import java.util.Objects; diff --git a/prometeu-lsp/prometeu-lsp-api/src/test/java/p/studio/lsp/api/LspServerBootRequestTest.java b/prometeu-lsp/prometeu-lsp-api/src/test/java/p/studio/lsp/api/LspServerBootRequestTest.java index bd895b74..cc8c1e3a 100644 --- a/prometeu-lsp/prometeu-lsp-api/src/test/java/p/studio/lsp/api/LspServerBootRequestTest.java +++ b/prometeu-lsp/prometeu-lsp-api/src/test/java/p/studio/lsp/api/LspServerBootRequestTest.java @@ -1,6 +1,9 @@ package p.studio.lsp.api; import org.junit.jupiter.api.Test; +import p.studio.lsp.messages.LspProjectContext; +import p.studio.lsp.messages.LspServerBootRequest; +import p.studio.lsp.messages.LspServerConfiguration; import java.nio.file.Path; diff --git a/prometeu-lsp/prometeu-lsp-v1/src/main/java/p/studio/lsp/v1/compiler/BaselineDocumentAnalysis.java b/prometeu-lsp/prometeu-lsp-v1/src/main/java/p/studio/lsp/messages/BaselineDocumentAnalysis.java similarity index 88% rename from prometeu-lsp/prometeu-lsp-v1/src/main/java/p/studio/lsp/v1/compiler/BaselineDocumentAnalysis.java rename to prometeu-lsp/prometeu-lsp-v1/src/main/java/p/studio/lsp/messages/BaselineDocumentAnalysis.java index edb457fe..1c43c4eb 100644 --- a/prometeu-lsp/prometeu-lsp-v1/src/main/java/p/studio/lsp/v1/compiler/BaselineDocumentAnalysis.java +++ b/prometeu-lsp/prometeu-lsp-v1/src/main/java/p/studio/lsp/messages/BaselineDocumentAnalysis.java @@ -1,4 +1,4 @@ -package p.studio.lsp.v1.compiler; +package p.studio.lsp.messages; import java.util.List; import java.util.Objects; diff --git a/prometeu-lsp/prometeu-lsp-v1/src/main/java/p/studio/lsp/v1/compiler/BaselineDocumentIssue.java b/prometeu-lsp/prometeu-lsp-v1/src/main/java/p/studio/lsp/messages/BaselineDocumentIssue.java similarity index 95% rename from prometeu-lsp/prometeu-lsp-v1/src/main/java/p/studio/lsp/v1/compiler/BaselineDocumentIssue.java rename to prometeu-lsp/prometeu-lsp-v1/src/main/java/p/studio/lsp/messages/BaselineDocumentIssue.java index 6b19dc8d..7ee61cb9 100644 --- a/prometeu-lsp/prometeu-lsp-v1/src/main/java/p/studio/lsp/v1/compiler/BaselineDocumentIssue.java +++ b/prometeu-lsp/prometeu-lsp-v1/src/main/java/p/studio/lsp/messages/BaselineDocumentIssue.java @@ -1,4 +1,4 @@ -package p.studio.lsp.v1.compiler; +package p.studio.lsp.messages; import java.util.Objects; diff --git a/prometeu-lsp/prometeu-lsp-v1/src/main/java/p/studio/lsp/v1/compiler/BaselineHover.java b/prometeu-lsp/prometeu-lsp-v1/src/main/java/p/studio/lsp/messages/BaselineHover.java similarity index 91% rename from prometeu-lsp/prometeu-lsp-v1/src/main/java/p/studio/lsp/v1/compiler/BaselineHover.java rename to prometeu-lsp/prometeu-lsp-v1/src/main/java/p/studio/lsp/messages/BaselineHover.java index 46efc4d2..5b795586 100644 --- a/prometeu-lsp/prometeu-lsp-v1/src/main/java/p/studio/lsp/v1/compiler/BaselineHover.java +++ b/prometeu-lsp/prometeu-lsp-v1/src/main/java/p/studio/lsp/messages/BaselineHover.java @@ -1,4 +1,4 @@ -package p.studio.lsp.v1.compiler; +package p.studio.lsp.messages; import java.util.Objects; diff --git a/prometeu-lsp/prometeu-lsp-v1/src/main/java/p/studio/lsp/v1/compiler/BaselineIssueSeverity.java b/prometeu-lsp/prometeu-lsp-v1/src/main/java/p/studio/lsp/messages/BaselineIssueSeverity.java similarity index 69% rename from prometeu-lsp/prometeu-lsp-v1/src/main/java/p/studio/lsp/v1/compiler/BaselineIssueSeverity.java rename to prometeu-lsp/prometeu-lsp-v1/src/main/java/p/studio/lsp/messages/BaselineIssueSeverity.java index f6f7caa8..2624a846 100644 --- a/prometeu-lsp/prometeu-lsp-v1/src/main/java/p/studio/lsp/v1/compiler/BaselineIssueSeverity.java +++ b/prometeu-lsp/prometeu-lsp-v1/src/main/java/p/studio/lsp/messages/BaselineIssueSeverity.java @@ -1,4 +1,4 @@ -package p.studio.lsp.v1.compiler; +package p.studio.lsp.messages; public enum BaselineIssueSeverity { INFORMATION, diff --git a/prometeu-lsp/prometeu-lsp-v1/src/main/java/p/studio/lsp/v1/compiler/BaselineServerDescription.java b/prometeu-lsp/prometeu-lsp-v1/src/main/java/p/studio/lsp/messages/BaselineServerDescription.java similarity index 94% rename from prometeu-lsp/prometeu-lsp-v1/src/main/java/p/studio/lsp/v1/compiler/BaselineServerDescription.java rename to prometeu-lsp/prometeu-lsp-v1/src/main/java/p/studio/lsp/messages/BaselineServerDescription.java index dab48834..2fc747a9 100644 --- a/prometeu-lsp/prometeu-lsp-v1/src/main/java/p/studio/lsp/v1/compiler/BaselineServerDescription.java +++ b/prometeu-lsp/prometeu-lsp-v1/src/main/java/p/studio/lsp/messages/BaselineServerDescription.java @@ -1,4 +1,4 @@ -package p.studio.lsp.v1.compiler; +package p.studio.lsp.messages; import java.util.Objects; diff --git a/prometeu-lsp/prometeu-lsp-v1/src/main/java/p/studio/lsp/v1/compiler/LanguageServiceBridge.java b/prometeu-lsp/prometeu-lsp-v1/src/main/java/p/studio/lsp/services/LanguageServiceBridge.java similarity index 62% rename from prometeu-lsp/prometeu-lsp-v1/src/main/java/p/studio/lsp/v1/compiler/LanguageServiceBridge.java rename to prometeu-lsp/prometeu-lsp-v1/src/main/java/p/studio/lsp/services/LanguageServiceBridge.java index 689d6fd2..38cef196 100644 --- a/prometeu-lsp/prometeu-lsp-v1/src/main/java/p/studio/lsp/v1/compiler/LanguageServiceBridge.java +++ b/prometeu-lsp/prometeu-lsp-v1/src/main/java/p/studio/lsp/services/LanguageServiceBridge.java @@ -1,6 +1,9 @@ -package p.studio.lsp.v1.compiler; +package p.studio.lsp.services; -import p.studio.lsp.api.LspProjectContext; +import p.studio.lsp.messages.BaselineDocumentAnalysis; +import p.studio.lsp.messages.BaselineHover; +import p.studio.lsp.messages.BaselineServerDescription; +import p.studio.lsp.messages.LspProjectContext; public interface LanguageServiceBridge { BaselineServerDescription describeServer(LspProjectContext project); diff --git a/prometeu-lsp/prometeu-lsp-v1/src/main/java/p/studio/lsp/v1/bootstrap/LspV1ServerLifecycle.java b/prometeu-lsp/prometeu-lsp-v1/src/main/java/p/studio/lsp/services/LspServerLifecycle.java similarity index 82% rename from prometeu-lsp/prometeu-lsp-v1/src/main/java/p/studio/lsp/v1/bootstrap/LspV1ServerLifecycle.java rename to prometeu-lsp/prometeu-lsp-v1/src/main/java/p/studio/lsp/services/LspServerLifecycle.java index 40c6e258..bab34c5c 100644 --- a/prometeu-lsp/prometeu-lsp-v1/src/main/java/p/studio/lsp/v1/bootstrap/LspV1ServerLifecycle.java +++ b/prometeu-lsp/prometeu-lsp-v1/src/main/java/p/studio/lsp/services/LspServerLifecycle.java @@ -1,23 +1,22 @@ -package p.studio.lsp.v1.bootstrap; +package p.studio.lsp.services; -import p.studio.lsp.api.LspProjectContext; -import p.studio.lsp.api.LspServerBootRequest; -import p.studio.lsp.api.LspServerHandle; -import p.studio.lsp.api.LspServerLifecycle; -import p.studio.lsp.v1.compiler.CompilerLanguageServiceBridge; -import p.studio.lsp.v1.host.ProjectScopedLspServerHost; -import p.studio.lsp.v1.host.ProjectScopedLspServerHostFactory; +import p.studio.lsp.messages.LspProjectContext; +import p.studio.lsp.messages.LspServerBootRequest; +import p.studio.lsp.messages.LspServerHandle; +import p.studio.lsp.services.compiler.CompilerLanguageServiceBridge; +import p.studio.lsp.services.host.ProjectScopedLspServerHost; +import p.studio.lsp.services.host.ProjectScopedLspServerHostFactory; import java.util.Objects; import java.util.concurrent.ConcurrentHashMap; import java.util.concurrent.ConcurrentMap; -public final class LspV1ServerLifecycle implements LspServerLifecycle { +public final class LspServerLifecycle implements p.studio.lsp.api.LspServerLifecycle { private final ProjectScopedLspServerHostFactory serverHostFactory; private final CompilerLanguageServiceBridge compilerBridge; private final ConcurrentMap activeServers; - public LspV1ServerLifecycle( + public LspServerLifecycle( final ProjectScopedLspServerHostFactory serverHostFactory, final CompilerLanguageServiceBridge compilerBridge) { this.serverHostFactory = Objects.requireNonNull(serverHostFactory, "serverHostFactory"); diff --git a/prometeu-lsp/prometeu-lsp-v1/src/main/java/p/studio/lsp/v1/compiler/CompilerLanguageServiceBridge.java b/prometeu-lsp/prometeu-lsp-v1/src/main/java/p/studio/lsp/services/compiler/CompilerLanguageServiceBridge.java similarity index 95% rename from prometeu-lsp/prometeu-lsp-v1/src/main/java/p/studio/lsp/v1/compiler/CompilerLanguageServiceBridge.java rename to prometeu-lsp/prometeu-lsp-v1/src/main/java/p/studio/lsp/services/compiler/CompilerLanguageServiceBridge.java index 8021ec50..375f5c29 100644 --- a/prometeu-lsp/prometeu-lsp-v1/src/main/java/p/studio/lsp/v1/compiler/CompilerLanguageServiceBridge.java +++ b/prometeu-lsp/prometeu-lsp-v1/src/main/java/p/studio/lsp/services/compiler/CompilerLanguageServiceBridge.java @@ -1,7 +1,8 @@ -package p.studio.lsp.v1.compiler; +package p.studio.lsp.services.compiler; import p.studio.compiler.workspaces.BuilderPipelineService; -import p.studio.lsp.api.LspProjectContext; +import p.studio.lsp.messages.*; +import p.studio.lsp.services.LanguageServiceBridge; import java.util.Objects; diff --git a/prometeu-lsp/prometeu-lsp-v1/src/main/java/p/studio/lsp/v1/host/ProjectScopedLspServerHost.java b/prometeu-lsp/prometeu-lsp-v1/src/main/java/p/studio/lsp/services/host/ProjectScopedLspServerHost.java similarity index 64% rename from prometeu-lsp/prometeu-lsp-v1/src/main/java/p/studio/lsp/v1/host/ProjectScopedLspServerHost.java rename to prometeu-lsp/prometeu-lsp-v1/src/main/java/p/studio/lsp/services/host/ProjectScopedLspServerHost.java index b3a847a5..a5263266 100644 --- a/prometeu-lsp/prometeu-lsp-v1/src/main/java/p/studio/lsp/v1/host/ProjectScopedLspServerHost.java +++ b/prometeu-lsp/prometeu-lsp-v1/src/main/java/p/studio/lsp/services/host/ProjectScopedLspServerHost.java @@ -1,6 +1,6 @@ -package p.studio.lsp.v1.host; +package p.studio.lsp.services.host; -import p.studio.lsp.api.LspServerEndpoint; +import p.studio.lsp.messages.LspServerEndpoint; public interface ProjectScopedLspServerHost extends AutoCloseable { LspServerEndpoint start(); diff --git a/prometeu-lsp/prometeu-lsp-v1/src/main/java/p/studio/lsp/v1/host/ProjectScopedLspServerHostFactory.java b/prometeu-lsp/prometeu-lsp-v1/src/main/java/p/studio/lsp/services/host/ProjectScopedLspServerHostFactory.java similarity index 55% rename from prometeu-lsp/prometeu-lsp-v1/src/main/java/p/studio/lsp/v1/host/ProjectScopedLspServerHostFactory.java rename to prometeu-lsp/prometeu-lsp-v1/src/main/java/p/studio/lsp/services/host/ProjectScopedLspServerHostFactory.java index 8b46b58a..130c764e 100644 --- a/prometeu-lsp/prometeu-lsp-v1/src/main/java/p/studio/lsp/v1/host/ProjectScopedLspServerHostFactory.java +++ b/prometeu-lsp/prometeu-lsp-v1/src/main/java/p/studio/lsp/services/host/ProjectScopedLspServerHostFactory.java @@ -1,7 +1,7 @@ -package p.studio.lsp.v1.host; +package p.studio.lsp.services.host; -import p.studio.lsp.api.LspServerBootRequest; -import p.studio.lsp.v1.compiler.CompilerLanguageServiceBridge; +import p.studio.lsp.messages.LspServerBootRequest; +import p.studio.lsp.services.compiler.CompilerLanguageServiceBridge; public interface ProjectScopedLspServerHostFactory { ProjectScopedLspServerHost create( diff --git a/prometeu-lsp/prometeu-lsp-v1/src/main/java/p/studio/lsp/v1/host/TcpLspServerHost.java b/prometeu-lsp/prometeu-lsp-v1/src/main/java/p/studio/lsp/services/host/TcpLspServerHost.java similarity index 93% rename from prometeu-lsp/prometeu-lsp-v1/src/main/java/p/studio/lsp/v1/host/TcpLspServerHost.java rename to prometeu-lsp/prometeu-lsp-v1/src/main/java/p/studio/lsp/services/host/TcpLspServerHost.java index 5d14c2c6..f01a4388 100644 --- a/prometeu-lsp/prometeu-lsp-v1/src/main/java/p/studio/lsp/v1/host/TcpLspServerHost.java +++ b/prometeu-lsp/prometeu-lsp-v1/src/main/java/p/studio/lsp/services/host/TcpLspServerHost.java @@ -1,12 +1,12 @@ -package p.studio.lsp.v1.host; +package p.studio.lsp.services.host; import org.eclipse.lsp4j.jsonrpc.Launcher; import org.eclipse.lsp4j.launch.LSPLauncher; import org.eclipse.lsp4j.services.LanguageClient; -import p.studio.lsp.api.LspServerBootRequest; -import p.studio.lsp.api.LspServerEndpoint; -import p.studio.lsp.v1.compiler.CompilerLanguageServiceBridge; -import p.studio.lsp.v1.protocol.PrometeuLanguageServer; +import p.studio.lsp.messages.LspServerBootRequest; +import p.studio.lsp.messages.LspServerEndpoint; +import p.studio.lsp.services.compiler.CompilerLanguageServiceBridge; +import p.studio.lsp.services.protocol.PrometeuLanguageServer; import java.io.IOException; import java.net.InetAddress; diff --git a/prometeu-lsp/prometeu-lsp-v1/src/main/java/p/studio/lsp/v1/host/TcpLspServerHostFactory.java b/prometeu-lsp/prometeu-lsp-v1/src/main/java/p/studio/lsp/services/host/TcpLspServerHostFactory.java similarity index 68% rename from prometeu-lsp/prometeu-lsp-v1/src/main/java/p/studio/lsp/v1/host/TcpLspServerHostFactory.java rename to prometeu-lsp/prometeu-lsp-v1/src/main/java/p/studio/lsp/services/host/TcpLspServerHostFactory.java index d8713f5a..465d5f7e 100644 --- a/prometeu-lsp/prometeu-lsp-v1/src/main/java/p/studio/lsp/v1/host/TcpLspServerHostFactory.java +++ b/prometeu-lsp/prometeu-lsp-v1/src/main/java/p/studio/lsp/services/host/TcpLspServerHostFactory.java @@ -1,7 +1,7 @@ -package p.studio.lsp.v1.host; +package p.studio.lsp.services.host; -import p.studio.lsp.api.LspServerBootRequest; -import p.studio.lsp.v1.compiler.CompilerLanguageServiceBridge; +import p.studio.lsp.messages.LspServerBootRequest; +import p.studio.lsp.services.compiler.CompilerLanguageServiceBridge; public final class TcpLspServerHostFactory implements ProjectScopedLspServerHostFactory { @Override diff --git a/prometeu-lsp/prometeu-lsp-v1/src/main/java/p/studio/lsp/v1/protocol/ProjectConnectionValidator.java b/prometeu-lsp/prometeu-lsp-v1/src/main/java/p/studio/lsp/services/protocol/ProjectConnectionValidator.java similarity index 97% rename from prometeu-lsp/prometeu-lsp-v1/src/main/java/p/studio/lsp/v1/protocol/ProjectConnectionValidator.java rename to prometeu-lsp/prometeu-lsp-v1/src/main/java/p/studio/lsp/services/protocol/ProjectConnectionValidator.java index 2dbf3a64..9abb9c8a 100644 --- a/prometeu-lsp/prometeu-lsp-v1/src/main/java/p/studio/lsp/v1/protocol/ProjectConnectionValidator.java +++ b/prometeu-lsp/prometeu-lsp-v1/src/main/java/p/studio/lsp/services/protocol/ProjectConnectionValidator.java @@ -1,11 +1,11 @@ -package p.studio.lsp.v1.protocol; +package p.studio.lsp.services.protocol; import org.eclipse.lsp4j.InitializeParams; import org.eclipse.lsp4j.WorkspaceFolder; import org.eclipse.lsp4j.jsonrpc.ResponseErrorException; import org.eclipse.lsp4j.jsonrpc.messages.ResponseError; import org.eclipse.lsp4j.jsonrpc.messages.ResponseErrorCode; -import p.studio.lsp.api.LspProjectContext; +import p.studio.lsp.messages.LspProjectContext; import java.net.URI; import java.nio.file.Path; diff --git a/prometeu-lsp/prometeu-lsp-v1/src/main/java/p/studio/lsp/v1/protocol/PrometeuLanguageServer.java b/prometeu-lsp/prometeu-lsp-v1/src/main/java/p/studio/lsp/services/protocol/PrometeuLanguageServer.java similarity index 85% rename from prometeu-lsp/prometeu-lsp-v1/src/main/java/p/studio/lsp/v1/protocol/PrometeuLanguageServer.java rename to prometeu-lsp/prometeu-lsp-v1/src/main/java/p/studio/lsp/services/protocol/PrometeuLanguageServer.java index 2a467e08..aa394d19 100644 --- a/prometeu-lsp/prometeu-lsp-v1/src/main/java/p/studio/lsp/v1/protocol/PrometeuLanguageServer.java +++ b/prometeu-lsp/prometeu-lsp-v1/src/main/java/p/studio/lsp/services/protocol/PrometeuLanguageServer.java @@ -1,4 +1,4 @@ -package p.studio.lsp.v1.protocol; +package p.studio.lsp.services.protocol; import org.eclipse.lsp4j.*; import org.eclipse.lsp4j.services.LanguageClient; @@ -6,11 +6,11 @@ import org.eclipse.lsp4j.services.LanguageClientAware; import org.eclipse.lsp4j.services.LanguageServer; import org.eclipse.lsp4j.services.TextDocumentService; import org.eclipse.lsp4j.services.WorkspaceService; -import p.studio.lsp.api.LspProjectContext; -import p.studio.lsp.v1.compiler.CompilerLanguageServiceBridge; -import p.studio.lsp.v1.compiler.LanguageServiceBridge; -import p.studio.lsp.v1.protocol.mapping.Lsp4jProtocolMessageMapper; -import p.studio.lsp.v1.protocol.mapping.ProtocolMessageMapper; +import p.studio.lsp.messages.LspProjectContext; +import p.studio.lsp.services.compiler.CompilerLanguageServiceBridge; +import p.studio.lsp.services.LanguageServiceBridge; +import p.studio.lsp.services.protocol.mapping.Lsp4jProtocolMessageMapper; +import p.studio.lsp.services.protocol.mapping.ProtocolMessageMapper; import java.util.Objects; import java.util.concurrent.CompletableFuture; @@ -62,8 +62,11 @@ public final class PrometeuLanguageServer implements LanguageServer, LanguageCli try { ProjectConnectionValidator.validateProjectBinding(project, params); } catch (RuntimeException runtimeException) { - client.logMessage(protocolMessageMapper.mapInfoMessage( - "Failed to initialize Prometeu Studio LSP for project " + project.projectKey() + ": " + runtimeException.getMessage())); + final LanguageClient currentClient = client; + if (currentClient != null) { + currentClient.logMessage(protocolMessageMapper.mapInfoMessage( + "Failed to initialize Prometeu Studio LSP for project " + project.projectKey() + ": " + runtimeException.getMessage())); + } return CompletableFuture.failedFuture(runtimeException); } return CompletableFuture.completedFuture(protocolMessageMapper.mapInitializeResult( diff --git a/prometeu-lsp/prometeu-lsp-v1/src/main/java/p/studio/lsp/v1/protocol/PrometeuTextDocumentService.java b/prometeu-lsp/prometeu-lsp-v1/src/main/java/p/studio/lsp/services/protocol/PrometeuTextDocumentService.java similarity index 93% rename from prometeu-lsp/prometeu-lsp-v1/src/main/java/p/studio/lsp/v1/protocol/PrometeuTextDocumentService.java rename to prometeu-lsp/prometeu-lsp-v1/src/main/java/p/studio/lsp/services/protocol/PrometeuTextDocumentService.java index c81edb55..903bab5f 100644 --- a/prometeu-lsp/prometeu-lsp-v1/src/main/java/p/studio/lsp/v1/protocol/PrometeuTextDocumentService.java +++ b/prometeu-lsp/prometeu-lsp-v1/src/main/java/p/studio/lsp/services/protocol/PrometeuTextDocumentService.java @@ -1,11 +1,11 @@ -package p.studio.lsp.v1.protocol; +package p.studio.lsp.services.protocol; import org.eclipse.lsp4j.*; import org.eclipse.lsp4j.services.LanguageClient; import org.eclipse.lsp4j.services.TextDocumentService; -import p.studio.lsp.api.LspProjectContext; -import p.studio.lsp.v1.compiler.LanguageServiceBridge; -import p.studio.lsp.v1.protocol.mapping.ProtocolMessageMapper; +import p.studio.lsp.messages.LspProjectContext; +import p.studio.lsp.services.LanguageServiceBridge; +import p.studio.lsp.services.protocol.mapping.ProtocolMessageMapper; import java.util.Objects; import java.util.concurrent.CompletableFuture; diff --git a/prometeu-lsp/prometeu-lsp-v1/src/main/java/p/studio/lsp/v1/protocol/PrometeuWorkspaceService.java b/prometeu-lsp/prometeu-lsp-v1/src/main/java/p/studio/lsp/services/protocol/PrometeuWorkspaceService.java similarity index 91% rename from prometeu-lsp/prometeu-lsp-v1/src/main/java/p/studio/lsp/v1/protocol/PrometeuWorkspaceService.java rename to prometeu-lsp/prometeu-lsp-v1/src/main/java/p/studio/lsp/services/protocol/PrometeuWorkspaceService.java index 1a5efa8e..612f9dd7 100644 --- a/prometeu-lsp/prometeu-lsp-v1/src/main/java/p/studio/lsp/v1/protocol/PrometeuWorkspaceService.java +++ b/prometeu-lsp/prometeu-lsp-v1/src/main/java/p/studio/lsp/services/protocol/PrometeuWorkspaceService.java @@ -1,4 +1,4 @@ -package p.studio.lsp.v1.protocol; +package p.studio.lsp.services.protocol; import org.eclipse.lsp4j.DidChangeConfigurationParams; import org.eclipse.lsp4j.DidChangeWatchedFilesParams; diff --git a/prometeu-lsp/prometeu-lsp-v1/src/main/java/p/studio/lsp/v1/protocol/mapping/Lsp4jProtocolMessageMapper.java b/prometeu-lsp/prometeu-lsp-v1/src/main/java/p/studio/lsp/services/protocol/mapping/Lsp4jProtocolMessageMapper.java similarity index 97% rename from prometeu-lsp/prometeu-lsp-v1/src/main/java/p/studio/lsp/v1/protocol/mapping/Lsp4jProtocolMessageMapper.java rename to prometeu-lsp/prometeu-lsp-v1/src/main/java/p/studio/lsp/services/protocol/mapping/Lsp4jProtocolMessageMapper.java index 8b9cf2bd..c6272e51 100644 --- a/prometeu-lsp/prometeu-lsp-v1/src/main/java/p/studio/lsp/v1/protocol/mapping/Lsp4jProtocolMessageMapper.java +++ b/prometeu-lsp/prometeu-lsp-v1/src/main/java/p/studio/lsp/services/protocol/mapping/Lsp4jProtocolMessageMapper.java @@ -1,7 +1,7 @@ -package p.studio.lsp.v1.protocol.mapping; +package p.studio.lsp.services.protocol.mapping; import org.eclipse.lsp4j.*; -import p.studio.lsp.v1.compiler.*; +import p.studio.lsp.messages.*; import java.util.List; diff --git a/prometeu-lsp/prometeu-lsp-v1/src/main/java/p/studio/lsp/v1/protocol/mapping/ProtocolMessageMapper.java b/prometeu-lsp/prometeu-lsp-v1/src/main/java/p/studio/lsp/services/protocol/mapping/ProtocolMessageMapper.java similarity index 74% rename from prometeu-lsp/prometeu-lsp-v1/src/main/java/p/studio/lsp/v1/protocol/mapping/ProtocolMessageMapper.java rename to prometeu-lsp/prometeu-lsp-v1/src/main/java/p/studio/lsp/services/protocol/mapping/ProtocolMessageMapper.java index 83d09bd1..d934411e 100644 --- a/prometeu-lsp/prometeu-lsp-v1/src/main/java/p/studio/lsp/v1/protocol/mapping/ProtocolMessageMapper.java +++ b/prometeu-lsp/prometeu-lsp-v1/src/main/java/p/studio/lsp/services/protocol/mapping/ProtocolMessageMapper.java @@ -1,12 +1,12 @@ -package p.studio.lsp.v1.protocol.mapping; +package p.studio.lsp.services.protocol.mapping; import org.eclipse.lsp4j.Hover; import org.eclipse.lsp4j.InitializeResult; import org.eclipse.lsp4j.MessageParams; import org.eclipse.lsp4j.PublishDiagnosticsParams; -import p.studio.lsp.v1.compiler.BaselineDocumentAnalysis; -import p.studio.lsp.v1.compiler.BaselineHover; -import p.studio.lsp.v1.compiler.BaselineServerDescription; +import p.studio.lsp.messages.BaselineDocumentAnalysis; +import p.studio.lsp.messages.BaselineHover; +import p.studio.lsp.messages.BaselineServerDescription; public interface ProtocolMessageMapper { InitializeResult mapInitializeResult(BaselineServerDescription description); diff --git a/prometeu-lsp/prometeu-lsp-v1/src/test/java/p/studio/lsp/v1/bootstrap/LspV1ServerLifecycleTest.java b/prometeu-lsp/prometeu-lsp-v1/src/test/java/p/studio/lsp/services/LspServerLifecycleTest.java similarity index 73% rename from prometeu-lsp/prometeu-lsp-v1/src/test/java/p/studio/lsp/v1/bootstrap/LspV1ServerLifecycleTest.java rename to prometeu-lsp/prometeu-lsp-v1/src/test/java/p/studio/lsp/services/LspServerLifecycleTest.java index 38aa03b1..0d576e87 100644 --- a/prometeu-lsp/prometeu-lsp-v1/src/test/java/p/studio/lsp/v1/bootstrap/LspV1ServerLifecycleTest.java +++ b/prometeu-lsp/prometeu-lsp-v1/src/test/java/p/studio/lsp/services/LspServerLifecycleTest.java @@ -1,12 +1,12 @@ -package p.studio.lsp.v1.bootstrap; +package p.studio.lsp.services; import org.junit.jupiter.api.Test; -import p.studio.lsp.api.LspProjectContext; -import p.studio.lsp.api.LspServerBootRequest; -import p.studio.lsp.api.LspServerEndpoint; -import p.studio.lsp.v1.compiler.CompilerLanguageServiceBridge; -import p.studio.lsp.v1.host.ProjectScopedLspServerHost; -import p.studio.lsp.v1.host.ProjectScopedLspServerHostFactory; +import p.studio.lsp.messages.LspProjectContext; +import p.studio.lsp.messages.LspServerBootRequest; +import p.studio.lsp.messages.LspServerEndpoint; +import p.studio.lsp.services.compiler.CompilerLanguageServiceBridge; +import p.studio.lsp.services.host.ProjectScopedLspServerHost; +import p.studio.lsp.services.host.ProjectScopedLspServerHostFactory; import java.nio.file.Path; @@ -14,13 +14,13 @@ import static org.junit.jupiter.api.Assertions.assertEquals; import static org.junit.jupiter.api.Assertions.assertThrows; import static org.junit.jupiter.api.Assertions.assertTrue; -class LspV1ServerLifecycleTest { +class LspServerLifecycleTest { @Test void lifecycleBootsAndShutsDownProjectScopedHost() { final FakeHost host = new FakeHost(); final ProjectScopedLspServerHostFactory factory = (request, compilerBridge) -> host; - final var lifecycle = new LspV1ServerLifecycle(factory, new CompilerLanguageServiceBridge()); + final var lifecycle = new LspServerLifecycle(factory, new CompilerLanguageServiceBridge()); final var project = new LspProjectContext("demo", "pbs", Path.of(".")); final var handle = lifecycle.bootServer(LspServerBootRequest.defaults(project)); @@ -37,7 +37,7 @@ class LspV1ServerLifecycleTest { @Test void lifecycleRejectsDoubleBootForSameProject() { final ProjectScopedLspServerHostFactory factory = (request, compilerBridge) -> new FakeHost(); - final var lifecycle = new LspV1ServerLifecycle(factory, new CompilerLanguageServiceBridge()); + final var lifecycle = new LspServerLifecycle(factory, new CompilerLanguageServiceBridge()); final var request = LspServerBootRequest.defaults(new LspProjectContext("demo", "pbs", Path.of("."))); lifecycle.bootServer(request); diff --git a/prometeu-lsp/prometeu-lsp-v1/src/test/java/p/studio/lsp/v1/boundary/LspV1BoundaryTest.java b/prometeu-lsp/prometeu-lsp-v1/src/test/java/p/studio/lsp/services/boundary/LspV1BoundaryTest.java similarity index 86% rename from prometeu-lsp/prometeu-lsp-v1/src/test/java/p/studio/lsp/v1/boundary/LspV1BoundaryTest.java rename to prometeu-lsp/prometeu-lsp-v1/src/test/java/p/studio/lsp/services/boundary/LspV1BoundaryTest.java index dc380fd7..2b09e71d 100644 --- a/prometeu-lsp/prometeu-lsp-v1/src/test/java/p/studio/lsp/v1/boundary/LspV1BoundaryTest.java +++ b/prometeu-lsp/prometeu-lsp-v1/src/test/java/p/studio/lsp/services/boundary/LspV1BoundaryTest.java @@ -1,4 +1,4 @@ -package p.studio.lsp.v1.boundary; +package p.studio.lsp.services.boundary; import org.junit.jupiter.api.Test; @@ -7,6 +7,7 @@ import java.nio.file.Files; import java.nio.file.Path; import java.util.List; +import static org.junit.jupiter.api.Assertions.assertFalse; import static org.junit.jupiter.api.Assertions.assertTrue; class LspV1BoundaryTest { @@ -39,8 +40,7 @@ class LspV1BoundaryTest { for (final Path javaFile : javaFiles) { final String source = Files.readString(javaFile); - assertTrue(!source.contains("org.eclipse.lsp4j"), - () -> "LSP4J leaked outside lsp-v1: " + javaFile); + assertFalse(source.contains("org.eclipse.lsp4j"), () -> "LSP4J leaked outside lsp-v1: " + javaFile); } } } diff --git a/prometeu-lsp/prometeu-lsp-v1/src/test/java/p/studio/lsp/v1/compiler/CompilerLanguageServiceBridgeTest.java b/prometeu-lsp/prometeu-lsp-v1/src/test/java/p/studio/lsp/services/compiler/CompilerLanguageServiceBridgeTest.java similarity index 82% rename from prometeu-lsp/prometeu-lsp-v1/src/test/java/p/studio/lsp/v1/compiler/CompilerLanguageServiceBridgeTest.java rename to prometeu-lsp/prometeu-lsp-v1/src/test/java/p/studio/lsp/services/compiler/CompilerLanguageServiceBridgeTest.java index 1db5da43..56c0735d 100644 --- a/prometeu-lsp/prometeu-lsp-v1/src/test/java/p/studio/lsp/v1/compiler/CompilerLanguageServiceBridgeTest.java +++ b/prometeu-lsp/prometeu-lsp-v1/src/test/java/p/studio/lsp/services/compiler/CompilerLanguageServiceBridgeTest.java @@ -1,7 +1,10 @@ -package p.studio.lsp.v1.compiler; +package p.studio.lsp.services.compiler; import org.junit.jupiter.api.Test; -import p.studio.lsp.api.LspProjectContext; +import p.studio.lsp.messages.BaselineDocumentAnalysis; +import p.studio.lsp.messages.BaselineHover; +import p.studio.lsp.messages.BaselineServerDescription; +import p.studio.lsp.messages.LspProjectContext; import java.nio.file.Path; diff --git a/prometeu-lsp/prometeu-lsp-v1/src/test/java/p/studio/lsp/v1/protocol/PrometeuLanguageServerTest.java b/prometeu-lsp/prometeu-lsp-v1/src/test/java/p/studio/lsp/services/protocol/PrometeuLanguageServerTest.java similarity index 94% rename from prometeu-lsp/prometeu-lsp-v1/src/test/java/p/studio/lsp/v1/protocol/PrometeuLanguageServerTest.java rename to prometeu-lsp/prometeu-lsp-v1/src/test/java/p/studio/lsp/services/protocol/PrometeuLanguageServerTest.java index 9c64cdba..66db3f0a 100644 --- a/prometeu-lsp/prometeu-lsp-v1/src/test/java/p/studio/lsp/v1/protocol/PrometeuLanguageServerTest.java +++ b/prometeu-lsp/prometeu-lsp-v1/src/test/java/p/studio/lsp/services/protocol/PrometeuLanguageServerTest.java @@ -1,4 +1,4 @@ -package p.studio.lsp.v1.protocol; +package p.studio.lsp.services.protocol; import org.eclipse.lsp4j.InitializeParams; import org.eclipse.lsp4j.InitializeResult; @@ -6,11 +6,13 @@ import org.eclipse.lsp4j.WorkspaceFolder; import org.eclipse.lsp4j.jsonrpc.ResponseErrorException; import org.eclipse.lsp4j.PublishDiagnosticsParams; import org.eclipse.lsp4j.services.TextDocumentService; -import org.eclipse.lsp4j.services.WorkspaceService; import org.junit.jupiter.api.Test; -import p.studio.lsp.api.LspProjectContext; -import p.studio.lsp.v1.compiler.*; -import p.studio.lsp.v1.protocol.mapping.ProtocolMessageMapper; +import p.studio.lsp.messages.BaselineDocumentAnalysis; +import p.studio.lsp.messages.BaselineHover; +import p.studio.lsp.messages.BaselineServerDescription; +import p.studio.lsp.messages.LspProjectContext; +import p.studio.lsp.services.LanguageServiceBridge; +import p.studio.lsp.services.protocol.mapping.ProtocolMessageMapper; import java.nio.file.Path; import java.util.List; diff --git a/prometeu-lsp/prometeu-lsp-v1/src/test/java/p/studio/lsp/v1/protocol/PrometeuTextDocumentServiceTest.java b/prometeu-lsp/prometeu-lsp-v1/src/test/java/p/studio/lsp/services/protocol/PrometeuTextDocumentServiceTest.java similarity index 96% rename from prometeu-lsp/prometeu-lsp-v1/src/test/java/p/studio/lsp/v1/protocol/PrometeuTextDocumentServiceTest.java rename to prometeu-lsp/prometeu-lsp-v1/src/test/java/p/studio/lsp/services/protocol/PrometeuTextDocumentServiceTest.java index a1e05504..3deccbd5 100644 --- a/prometeu-lsp/prometeu-lsp-v1/src/test/java/p/studio/lsp/v1/protocol/PrometeuTextDocumentServiceTest.java +++ b/prometeu-lsp/prometeu-lsp-v1/src/test/java/p/studio/lsp/services/protocol/PrometeuTextDocumentServiceTest.java @@ -1,11 +1,11 @@ -package p.studio.lsp.v1.protocol; +package p.studio.lsp.services.protocol; import org.eclipse.lsp4j.*; import org.eclipse.lsp4j.services.LanguageClient; import org.junit.jupiter.api.Test; -import p.studio.lsp.api.LspProjectContext; -import p.studio.lsp.v1.compiler.*; -import p.studio.lsp.v1.protocol.mapping.ProtocolMessageMapper; +import p.studio.lsp.messages.*; +import p.studio.lsp.services.LanguageServiceBridge; +import p.studio.lsp.services.protocol.mapping.ProtocolMessageMapper; import java.nio.file.Path; import java.util.List; diff --git a/prometeu-studio/src/main/java/p/studio/projectsessions/StudioProjectSession.java b/prometeu-studio/src/main/java/p/studio/projectsessions/StudioProjectSession.java index 3e2b08b5..037e06ef 100644 --- a/prometeu-studio/src/main/java/p/studio/projectsessions/StudioProjectSession.java +++ b/prometeu-studio/src/main/java/p/studio/projectsessions/StudioProjectSession.java @@ -1,8 +1,8 @@ package p.studio.projectsessions; import p.studio.execution.StudioExecutionSessionService; -import p.studio.lsp.api.LspProjectContext; -import p.studio.lsp.api.LspServerHandle; +import p.studio.lsp.messages.LspProjectContext; +import p.studio.lsp.messages.LspServerHandle; import p.studio.lsp.api.LspServerLifecycle; import p.studio.projectstate.ProjectLocalStudioSetup; import p.studio.projectstate.ProjectLocalStudioState; diff --git a/prometeu-studio/src/main/java/p/studio/projectsessions/StudioProjectSessionFactory.java b/prometeu-studio/src/main/java/p/studio/projectsessions/StudioProjectSessionFactory.java index 5258a7d3..dcebf551 100644 --- a/prometeu-studio/src/main/java/p/studio/projectsessions/StudioProjectSessionFactory.java +++ b/prometeu-studio/src/main/java/p/studio/projectsessions/StudioProjectSessionFactory.java @@ -1,8 +1,8 @@ package p.studio.projectsessions; -import p.studio.lsp.api.LspProjectContext; -import p.studio.lsp.api.LspServerBootRequest; -import p.studio.lsp.api.LspServerHandle; +import p.studio.lsp.messages.LspProjectContext; +import p.studio.lsp.messages.LspServerBootRequest; +import p.studio.lsp.messages.LspServerHandle; import p.studio.lsp.api.LspServerLifecycle; import p.studio.execution.StudioExecutionSessionService; import p.studio.projectstate.ProjectLocalStudioSetupService; diff --git a/prometeu-studio/src/test/java/p/studio/projectsessions/StudioProjectSessionFactoryTest.java b/prometeu-studio/src/test/java/p/studio/projectsessions/StudioProjectSessionFactoryTest.java index 6b2aa5fc..64cee709 100644 --- a/prometeu-studio/src/test/java/p/studio/projectsessions/StudioProjectSessionFactoryTest.java +++ b/prometeu-studio/src/test/java/p/studio/projectsessions/StudioProjectSessionFactoryTest.java @@ -1,10 +1,11 @@ package p.studio.projectsessions; import org.junit.jupiter.api.Test; -import p.studio.lsp.api.LspProjectContext; -import p.studio.lsp.api.LspServerBootRequest; -import p.studio.lsp.api.LspServerHandle; +import p.studio.lsp.messages.LspProjectContext; +import p.studio.lsp.messages.LspServerBootRequest; +import p.studio.lsp.messages.LspServerHandle; import p.studio.lsp.api.LspServerLifecycle; +import p.studio.lsp.messages.LspServerEndpoint; import p.studio.projectstate.ProjectLocalStudioSetup; import p.studio.projectstate.ProjectLocalStudioSetupService; import p.studio.projectstate.ProjectLocalStudioState; @@ -105,7 +106,7 @@ final class StudioProjectSessionFactoryTest { lastRequest = request; return new LspServerHandle( request.project(), - new p.studio.lsp.api.LspServerEndpoint("127.0.0.1", request.configuration().port())); + new LspServerEndpoint("127.0.0.1", request.configuration().port())); } @Override diff --git a/prometeu-studio/src/test/java/p/studio/projectsessions/StudioProjectSessionTest.java b/prometeu-studio/src/test/java/p/studio/projectsessions/StudioProjectSessionTest.java index f9a8eb8b..39753c34 100644 --- a/prometeu-studio/src/test/java/p/studio/projectsessions/StudioProjectSessionTest.java +++ b/prometeu-studio/src/test/java/p/studio/projectsessions/StudioProjectSessionTest.java @@ -2,9 +2,11 @@ package p.studio.projectsessions; import org.junit.jupiter.api.Test; import p.studio.execution.StudioExecutionSessionService; -import p.studio.lsp.api.LspProjectContext; -import p.studio.lsp.api.LspServerHandle; +import p.studio.lsp.messages.LspProjectContext; +import p.studio.lsp.messages.LspServerHandle; import p.studio.lsp.api.LspServerLifecycle; +import p.studio.lsp.messages.LspServerBootRequest; +import p.studio.lsp.messages.LspServerEndpoint; import p.studio.projectstate.ProjectLocalStudioSetup; import p.studio.projectstate.ProjectLocalStudioState; import p.studio.projectstate.ProjectLocalStudioStateService; @@ -61,7 +63,7 @@ final class StudioProjectSessionTest { final RecordingLspServerLifecycle lspServerLifecycle = new RecordingLspServerLifecycle(); final LspServerHandle lspServerHandle = new LspServerHandle( new LspProjectContext("demo", "pbs", Path.of("/tmp/example")), - new p.studio.lsp.api.LspServerEndpoint("127.0.0.1", 7777)); + new LspServerEndpoint("127.0.0.1", 7777)); final StudioProjectSession session = new StudioProjectSession( projectReference(), stateService, @@ -100,7 +102,7 @@ final class StudioProjectSessionTest { private LspProjectContext lastProject; @Override - public LspServerHandle bootServer(final p.studio.lsp.api.LspServerBootRequest request) { + public LspServerHandle bootServer(final LspServerBootRequest request) { throw new UnsupportedOperationException(); } -- 2.47.2 From 14d4751f9a75a4cefa150455be6b707157f664b7 Mon Sep 17 00:00:00 2001 From: bQUARKz Date: Wed, 6 May 2026 00:25:23 +0100 Subject: [PATCH 11/37] package moving --- prometeu-app/src/main/java/p/studio/AppContainer.java | 7 ++++--- ...LspServerLifecycle.java => LspServerLifecycleImpl.java} | 5 +++-- ...rLifecycleTest.java => LspServerLifecycleImplTest.java} | 6 +++--- 3 files changed, 10 insertions(+), 8 deletions(-) rename prometeu-lsp/prometeu-lsp-v1/src/main/java/p/studio/lsp/services/{LspServerLifecycle.java => LspServerLifecycleImpl.java} (94%) rename prometeu-lsp/prometeu-lsp-v1/src/test/java/p/studio/lsp/services/{LspServerLifecycleTest.java => LspServerLifecycleImplTest.java} (89%) diff --git a/prometeu-app/src/main/java/p/studio/AppContainer.java b/prometeu-app/src/main/java/p/studio/AppContainer.java index 6f84a69d..71a310e2 100644 --- a/prometeu-app/src/main/java/p/studio/AppContainer.java +++ b/prometeu-app/src/main/java/p/studio/AppContainer.java @@ -2,9 +2,10 @@ package p.studio; import com.fasterxml.jackson.databind.ObjectMapper; import p.packer.Packer; +import p.studio.lsp.api.LspServerLifecycle; import p.studio.lsp.events.StudioEventBus; import p.studio.lsp.events.StudioPackerEventAdapter; -import p.studio.lsp.services.LspServerLifecycle; +import p.studio.lsp.services.LspServerLifecycleImpl; import p.studio.lsp.services.compiler.CompilerLanguageServiceBridge; import p.studio.lsp.services.host.TcpLspServerHostFactory; import p.studio.utilities.ThemeService; @@ -22,7 +23,7 @@ public final class AppContainer implements Container { private final ObjectMapper mapper; private final EmbeddedPacker embeddedPacker; private final StudioBackgroundTasks backgroundTasks; - private final p.studio.lsp.api.LspServerLifecycle lspServerLifecycle; + private final LspServerLifecycle lspServerLifecycle; public AppContainer() { this.i18nService = new I18nService(); @@ -33,7 +34,7 @@ public final class AppContainer implements Container { this.backgroundTasks = new StudioBackgroundTasks(backgroundExecutor); final Packer packer = Packer.bootstrap(this.mapper, new StudioPackerEventAdapter(studioEventBus)); this.embeddedPacker = new EmbeddedPacker(packer.workspaceService(), packer::close); - this.lspServerLifecycle = new LspServerLifecycle( + this.lspServerLifecycle = new LspServerLifecycleImpl( new TcpLspServerHostFactory(), new CompilerLanguageServiceBridge()); } diff --git a/prometeu-lsp/prometeu-lsp-v1/src/main/java/p/studio/lsp/services/LspServerLifecycle.java b/prometeu-lsp/prometeu-lsp-v1/src/main/java/p/studio/lsp/services/LspServerLifecycleImpl.java similarity index 94% rename from prometeu-lsp/prometeu-lsp-v1/src/main/java/p/studio/lsp/services/LspServerLifecycle.java rename to prometeu-lsp/prometeu-lsp-v1/src/main/java/p/studio/lsp/services/LspServerLifecycleImpl.java index bab34c5c..af2744ea 100644 --- a/prometeu-lsp/prometeu-lsp-v1/src/main/java/p/studio/lsp/services/LspServerLifecycle.java +++ b/prometeu-lsp/prometeu-lsp-v1/src/main/java/p/studio/lsp/services/LspServerLifecycleImpl.java @@ -1,5 +1,6 @@ package p.studio.lsp.services; +import p.studio.lsp.api.LspServerLifecycle; import p.studio.lsp.messages.LspProjectContext; import p.studio.lsp.messages.LspServerBootRequest; import p.studio.lsp.messages.LspServerHandle; @@ -11,12 +12,12 @@ import java.util.Objects; import java.util.concurrent.ConcurrentHashMap; import java.util.concurrent.ConcurrentMap; -public final class LspServerLifecycle implements p.studio.lsp.api.LspServerLifecycle { +public final class LspServerLifecycleImpl implements LspServerLifecycle { private final ProjectScopedLspServerHostFactory serverHostFactory; private final CompilerLanguageServiceBridge compilerBridge; private final ConcurrentMap activeServers; - public LspServerLifecycle( + public LspServerLifecycleImpl( final ProjectScopedLspServerHostFactory serverHostFactory, final CompilerLanguageServiceBridge compilerBridge) { this.serverHostFactory = Objects.requireNonNull(serverHostFactory, "serverHostFactory"); diff --git a/prometeu-lsp/prometeu-lsp-v1/src/test/java/p/studio/lsp/services/LspServerLifecycleTest.java b/prometeu-lsp/prometeu-lsp-v1/src/test/java/p/studio/lsp/services/LspServerLifecycleImplTest.java similarity index 89% rename from prometeu-lsp/prometeu-lsp-v1/src/test/java/p/studio/lsp/services/LspServerLifecycleTest.java rename to prometeu-lsp/prometeu-lsp-v1/src/test/java/p/studio/lsp/services/LspServerLifecycleImplTest.java index 0d576e87..6d71a5f7 100644 --- a/prometeu-lsp/prometeu-lsp-v1/src/test/java/p/studio/lsp/services/LspServerLifecycleTest.java +++ b/prometeu-lsp/prometeu-lsp-v1/src/test/java/p/studio/lsp/services/LspServerLifecycleImplTest.java @@ -14,13 +14,13 @@ import static org.junit.jupiter.api.Assertions.assertEquals; import static org.junit.jupiter.api.Assertions.assertThrows; import static org.junit.jupiter.api.Assertions.assertTrue; -class LspServerLifecycleTest { +class LspServerLifecycleImplTest { @Test void lifecycleBootsAndShutsDownProjectScopedHost() { final FakeHost host = new FakeHost(); final ProjectScopedLspServerHostFactory factory = (request, compilerBridge) -> host; - final var lifecycle = new LspServerLifecycle(factory, new CompilerLanguageServiceBridge()); + final var lifecycle = new LspServerLifecycleImpl(factory, new CompilerLanguageServiceBridge()); final var project = new LspProjectContext("demo", "pbs", Path.of(".")); final var handle = lifecycle.bootServer(LspServerBootRequest.defaults(project)); @@ -37,7 +37,7 @@ class LspServerLifecycleTest { @Test void lifecycleRejectsDoubleBootForSameProject() { final ProjectScopedLspServerHostFactory factory = (request, compilerBridge) -> new FakeHost(); - final var lifecycle = new LspServerLifecycle(factory, new CompilerLanguageServiceBridge()); + final var lifecycle = new LspServerLifecycleImpl(factory, new CompilerLanguageServiceBridge()); final var request = LspServerBootRequest.defaults(new LspProjectContext("demo", "pbs", Path.of("."))); lifecycle.bootServer(request); -- 2.47.2 From 41f2c804a08ccd35ab5b38948fedb5a7dab12e9d Mon Sep 17 00:00:00 2001 From: bQUARKz Date: Wed, 6 May 2026 02:58:18 +0100 Subject: [PATCH 12/37] clean up and simplify --- .../src/main/java/p/studio/AppContainer.java | 6 +- .../p/studio/lsp/api/LspServerLifecycle.java | 7 +- .../lsp/messages/LspServerBootRequest.java | 17 - .../lsp/messages/LspServerConfiguration.java | 28 +- .../studio/lsp/messages/LspServerHandle.java | 13 - .../p/studio/lsp/api/LspApiBoundaryTest.java | 32 - .../lsp/api/LspServerBootRequestTest.java | 44 - .../lsp/services/LanguageServiceBridge.java | 8 +- .../lsp/services/LspServerLifecycleImpl.java | 37 +- .../services/{host => }/TcpLspServerHost.java | 35 +- .../lsp/services/TcpLspServerHostFactory.java | 14 + .../CompilerLanguageServiceBridge.java | 31 +- .../host/ProjectScopedLspServerHost.java | 10 - .../ProjectScopedLspServerHostFactory.java | 10 - .../host/TcpLspServerHostFactory.java | 13 - .../services/LspServerLifecycleImplTest.java | 63 -- .../services/boundary/LspV1BoundaryTest.java | 46 - .../CompilerLanguageServiceBridgeTest.java | 32 - .../protocol/PrometeuLanguageServerTest.java | 175 ---- .../PrometeuTextDocumentServiceTest.java | 141 ---- .../p/studio/projects/ProjectReference.java | 8 + .../projectsessions/StudioProjectSession.java | 17 +- .../StudioProjectSessionFactory.java | 19 +- .../StudioProjectSessionFactoryTest.java | 29 +- .../StudioProjectSessionTest.java | 19 +- .../main/assets/.prometeu/cache.json | 784 +++++++++--------- 26 files changed, 497 insertions(+), 1141 deletions(-) delete mode 100644 prometeu-lsp/prometeu-lsp-api/src/main/java/p/studio/lsp/messages/LspServerBootRequest.java delete mode 100644 prometeu-lsp/prometeu-lsp-api/src/main/java/p/studio/lsp/messages/LspServerHandle.java delete mode 100644 prometeu-lsp/prometeu-lsp-api/src/test/java/p/studio/lsp/api/LspApiBoundaryTest.java delete mode 100644 prometeu-lsp/prometeu-lsp-api/src/test/java/p/studio/lsp/api/LspServerBootRequestTest.java rename prometeu-lsp/prometeu-lsp-v1/src/main/java/p/studio/lsp/services/{host => }/TcpLspServerHost.java (74%) create mode 100644 prometeu-lsp/prometeu-lsp-v1/src/main/java/p/studio/lsp/services/TcpLspServerHostFactory.java delete mode 100644 prometeu-lsp/prometeu-lsp-v1/src/main/java/p/studio/lsp/services/host/ProjectScopedLspServerHost.java delete mode 100644 prometeu-lsp/prometeu-lsp-v1/src/main/java/p/studio/lsp/services/host/ProjectScopedLspServerHostFactory.java delete mode 100644 prometeu-lsp/prometeu-lsp-v1/src/main/java/p/studio/lsp/services/host/TcpLspServerHostFactory.java delete mode 100644 prometeu-lsp/prometeu-lsp-v1/src/test/java/p/studio/lsp/services/LspServerLifecycleImplTest.java delete mode 100644 prometeu-lsp/prometeu-lsp-v1/src/test/java/p/studio/lsp/services/boundary/LspV1BoundaryTest.java delete mode 100644 prometeu-lsp/prometeu-lsp-v1/src/test/java/p/studio/lsp/services/compiler/CompilerLanguageServiceBridgeTest.java delete mode 100644 prometeu-lsp/prometeu-lsp-v1/src/test/java/p/studio/lsp/services/protocol/PrometeuLanguageServerTest.java delete mode 100644 prometeu-lsp/prometeu-lsp-v1/src/test/java/p/studio/lsp/services/protocol/PrometeuTextDocumentServiceTest.java diff --git a/prometeu-app/src/main/java/p/studio/AppContainer.java b/prometeu-app/src/main/java/p/studio/AppContainer.java index 71a310e2..9b1851c5 100644 --- a/prometeu-app/src/main/java/p/studio/AppContainer.java +++ b/prometeu-app/src/main/java/p/studio/AppContainer.java @@ -6,8 +6,6 @@ import p.studio.lsp.api.LspServerLifecycle; import p.studio.lsp.events.StudioEventBus; import p.studio.lsp.events.StudioPackerEventAdapter; import p.studio.lsp.services.LspServerLifecycleImpl; -import p.studio.lsp.services.compiler.CompilerLanguageServiceBridge; -import p.studio.lsp.services.host.TcpLspServerHostFactory; import p.studio.utilities.ThemeService; import p.studio.utilities.i18n.I18nService; @@ -34,9 +32,7 @@ public final class AppContainer implements Container { this.backgroundTasks = new StudioBackgroundTasks(backgroundExecutor); final Packer packer = Packer.bootstrap(this.mapper, new StudioPackerEventAdapter(studioEventBus)); this.embeddedPacker = new EmbeddedPacker(packer.workspaceService(), packer::close); - this.lspServerLifecycle = new LspServerLifecycleImpl( - new TcpLspServerHostFactory(), - new CompilerLanguageServiceBridge()); + this.lspServerLifecycle = new LspServerLifecycleImpl(); } @Override diff --git a/prometeu-lsp/prometeu-lsp-api/src/main/java/p/studio/lsp/api/LspServerLifecycle.java b/prometeu-lsp/prometeu-lsp-api/src/main/java/p/studio/lsp/api/LspServerLifecycle.java index 749733de..564020b8 100644 --- a/prometeu-lsp/prometeu-lsp-api/src/main/java/p/studio/lsp/api/LspServerLifecycle.java +++ b/prometeu-lsp/prometeu-lsp-api/src/main/java/p/studio/lsp/api/LspServerLifecycle.java @@ -1,11 +1,10 @@ package p.studio.lsp.api; import p.studio.lsp.messages.LspProjectContext; -import p.studio.lsp.messages.LspServerBootRequest; -import p.studio.lsp.messages.LspServerHandle; +import p.studio.lsp.messages.LspServerConfiguration; public interface LspServerLifecycle { - LspServerHandle bootServer(LspServerBootRequest request); + void bootServer(LspServerConfiguration serverConfiguration, LspProjectContext context); - void shutdownServer(LspProjectContext project); + void shutdownServer(LspProjectContext context); } diff --git a/prometeu-lsp/prometeu-lsp-api/src/main/java/p/studio/lsp/messages/LspServerBootRequest.java b/prometeu-lsp/prometeu-lsp-api/src/main/java/p/studio/lsp/messages/LspServerBootRequest.java deleted file mode 100644 index ba3e057d..00000000 --- a/prometeu-lsp/prometeu-lsp-api/src/main/java/p/studio/lsp/messages/LspServerBootRequest.java +++ /dev/null @@ -1,17 +0,0 @@ -package p.studio.lsp.messages; - -import java.util.Objects; - -public record LspServerBootRequest( - LspProjectContext project, - LspServerConfiguration configuration) { - - public LspServerBootRequest { - project = Objects.requireNonNull(project, "project"); - configuration = Objects.requireNonNull(configuration, "configuration"); - } - - public static LspServerBootRequest defaults(final LspProjectContext project) { - return new LspServerBootRequest(project, LspServerConfiguration.defaults()); - } -} diff --git a/prometeu-lsp/prometeu-lsp-api/src/main/java/p/studio/lsp/messages/LspServerConfiguration.java b/prometeu-lsp/prometeu-lsp-api/src/main/java/p/studio/lsp/messages/LspServerConfiguration.java index 1307584f..3eb790d9 100644 --- a/prometeu-lsp/prometeu-lsp-api/src/main/java/p/studio/lsp/messages/LspServerConfiguration.java +++ b/prometeu-lsp/prometeu-lsp-api/src/main/java/p/studio/lsp/messages/LspServerConfiguration.java @@ -1,29 +1,19 @@ package p.studio.lsp.messages; -import java.util.Objects; +import lombok.Builder; +import lombok.Getter; -public record LspServerConfiguration( - String host, - int port) { +@Builder +@Getter +public class LspServerConfiguration { public static final String DEFAULT_HOST = "127.0.0.1"; public static final int DEFAULT_PORT = 7777; - public LspServerConfiguration { - host = requireHost(host); - if (port < 0 || port > 65535) { - throw new IllegalArgumentException("port must be between 0 and 65535"); - } - } + @Builder.Default + private final LspServerEndpoint endpoint = new LspServerEndpoint(DEFAULT_HOST, DEFAULT_PORT); + public static LspServerConfiguration defaults() { - return new LspServerConfiguration(DEFAULT_HOST, DEFAULT_PORT); - } - - private static String requireHost(final String value) { - final String candidate = Objects.requireNonNull(value, "host").trim(); - if (candidate.isEmpty()) { - throw new IllegalArgumentException("host must not be blank"); - } - return candidate; + return LspServerConfiguration.builder().build(); } } diff --git a/prometeu-lsp/prometeu-lsp-api/src/main/java/p/studio/lsp/messages/LspServerHandle.java b/prometeu-lsp/prometeu-lsp-api/src/main/java/p/studio/lsp/messages/LspServerHandle.java deleted file mode 100644 index b894435c..00000000 --- a/prometeu-lsp/prometeu-lsp-api/src/main/java/p/studio/lsp/messages/LspServerHandle.java +++ /dev/null @@ -1,13 +0,0 @@ -package p.studio.lsp.messages; - -import java.util.Objects; - -public record LspServerHandle( - LspProjectContext project, - LspServerEndpoint endpoint) { - - public LspServerHandle { - project = Objects.requireNonNull(project, "project"); - endpoint = Objects.requireNonNull(endpoint, "endpoint"); - } -} diff --git a/prometeu-lsp/prometeu-lsp-api/src/test/java/p/studio/lsp/api/LspApiBoundaryTest.java b/prometeu-lsp/prometeu-lsp-api/src/test/java/p/studio/lsp/api/LspApiBoundaryTest.java deleted file mode 100644 index 055b151c..00000000 --- a/prometeu-lsp/prometeu-lsp-api/src/test/java/p/studio/lsp/api/LspApiBoundaryTest.java +++ /dev/null @@ -1,32 +0,0 @@ -package p.studio.lsp.api; - -import org.junit.jupiter.api.Test; - -import java.io.IOException; -import java.nio.file.Files; -import java.nio.file.Path; -import java.util.List; - -import static org.junit.jupiter.api.Assertions.assertTrue; - -class LspApiBoundaryTest { - - @Test - void apiSourceMustRemainFreeOfLsp4jAndProtocolPackages() throws IOException { - final Path sourceRoot = Path.of("src/main/java"); - final List javaFiles; - try (var stream = Files.walk(sourceRoot)) { - javaFiles = stream - .filter(path -> path.toString().endsWith(".java")) - .toList(); - } - - for (final Path javaFile : javaFiles) { - final String source = Files.readString(javaFile); - assertTrue(!source.contains("org.eclipse.lsp4j"), - () -> "LSP4J leaked into lsp-api: " + javaFile); - assertTrue(!source.contains(".protocol."), - () -> "Protocol package leaked into lsp-api: " + javaFile); - } - } -} diff --git a/prometeu-lsp/prometeu-lsp-api/src/test/java/p/studio/lsp/api/LspServerBootRequestTest.java b/prometeu-lsp/prometeu-lsp-api/src/test/java/p/studio/lsp/api/LspServerBootRequestTest.java deleted file mode 100644 index cc8c1e3a..00000000 --- a/prometeu-lsp/prometeu-lsp-api/src/test/java/p/studio/lsp/api/LspServerBootRequestTest.java +++ /dev/null @@ -1,44 +0,0 @@ -package p.studio.lsp.api; - -import org.junit.jupiter.api.Test; -import p.studio.lsp.messages.LspProjectContext; -import p.studio.lsp.messages.LspServerBootRequest; -import p.studio.lsp.messages.LspServerConfiguration; - -import java.nio.file.Path; - -import static org.junit.jupiter.api.Assertions.assertEquals; -import static org.junit.jupiter.api.Assertions.assertThrows; - -class LspServerBootRequestTest { - - @Test - void defaultsUseDeterministicLoopbackConfiguration() { - final LspProjectContext project = new LspProjectContext("demo", "pbs", Path.of(".")); - - final LspServerBootRequest request = LspServerBootRequest.defaults(project); - - assertEquals(project, request.project()); - assertEquals(LspServerConfiguration.DEFAULT_HOST, request.configuration().host()); - assertEquals(LspServerConfiguration.DEFAULT_PORT, request.configuration().port()); - } - - @Test - void configurationRejectsInvalidValues() { - assertThrows(NullPointerException.class, () -> new LspServerConfiguration(null, 7777)); - assertThrows(IllegalArgumentException.class, () -> new LspServerConfiguration(" ", 7777)); - assertThrows(IllegalArgumentException.class, () -> new LspServerConfiguration("127.0.0.1", -1)); - } - - @Test - void projectContextNormalizesAndRejectsBlankFields() { - final LspProjectContext context = new LspProjectContext(" demo ", " pbs ", Path.of(".")); - - assertEquals("demo", context.projectKey()); - assertEquals("pbs", context.languageId()); - assertEquals(Path.of(".").toAbsolutePath().normalize(), context.projectRoot()); - - assertThrows(IllegalArgumentException.class, () -> new LspProjectContext(" ", "pbs", Path.of("."))); - assertThrows(IllegalArgumentException.class, () -> new LspProjectContext("demo", " ", Path.of("."))); - } -} diff --git a/prometeu-lsp/prometeu-lsp-v1/src/main/java/p/studio/lsp/services/LanguageServiceBridge.java b/prometeu-lsp/prometeu-lsp-v1/src/main/java/p/studio/lsp/services/LanguageServiceBridge.java index 38cef196..3b7f982b 100644 --- a/prometeu-lsp/prometeu-lsp-v1/src/main/java/p/studio/lsp/services/LanguageServiceBridge.java +++ b/prometeu-lsp/prometeu-lsp-v1/src/main/java/p/studio/lsp/services/LanguageServiceBridge.java @@ -6,11 +6,11 @@ import p.studio.lsp.messages.BaselineServerDescription; import p.studio.lsp.messages.LspProjectContext; public interface LanguageServiceBridge { - BaselineServerDescription describeServer(LspProjectContext project); + BaselineServerDescription describeServer(LspProjectContext context); - BaselineDocumentAnalysis analyzeDocument(LspProjectContext project, String documentUri, String text); + BaselineDocumentAnalysis analyzeDocument(LspProjectContext context, String documentUri, String text); - BaselineHover hover(LspProjectContext project, String documentUri, int line, int character); + BaselineHover hover(LspProjectContext context, String documentUri, int line, int character); - String onSave(LspProjectContext project, String documentUri); + String onSave(LspProjectContext context, String documentUri); } diff --git a/prometeu-lsp/prometeu-lsp-v1/src/main/java/p/studio/lsp/services/LspServerLifecycleImpl.java b/prometeu-lsp/prometeu-lsp-v1/src/main/java/p/studio/lsp/services/LspServerLifecycleImpl.java index af2744ea..9a85283d 100644 --- a/prometeu-lsp/prometeu-lsp-v1/src/main/java/p/studio/lsp/services/LspServerLifecycleImpl.java +++ b/prometeu-lsp/prometeu-lsp-v1/src/main/java/p/studio/lsp/services/LspServerLifecycleImpl.java @@ -2,43 +2,36 @@ package p.studio.lsp.services; import p.studio.lsp.api.LspServerLifecycle; import p.studio.lsp.messages.LspProjectContext; -import p.studio.lsp.messages.LspServerBootRequest; -import p.studio.lsp.messages.LspServerHandle; +import p.studio.lsp.messages.LspServerConfiguration; import p.studio.lsp.services.compiler.CompilerLanguageServiceBridge; -import p.studio.lsp.services.host.ProjectScopedLspServerHost; -import p.studio.lsp.services.host.ProjectScopedLspServerHostFactory; import java.util.Objects; import java.util.concurrent.ConcurrentHashMap; import java.util.concurrent.ConcurrentMap; public final class LspServerLifecycleImpl implements LspServerLifecycle { - private final ProjectScopedLspServerHostFactory serverHostFactory; + private final TcpLspServerHostFactory serverHostFactory; private final CompilerLanguageServiceBridge compilerBridge; - private final ConcurrentMap activeServers; + private final ConcurrentMap activeServers; - public LspServerLifecycleImpl( - final ProjectScopedLspServerHostFactory serverHostFactory, - final CompilerLanguageServiceBridge compilerBridge) { - this.serverHostFactory = Objects.requireNonNull(serverHostFactory, "serverHostFactory"); - this.compilerBridge = Objects.requireNonNull(compilerBridge, "compilerBridge"); + public LspServerLifecycleImpl() { + this.compilerBridge = new CompilerLanguageServiceBridge(); + this.serverHostFactory = new TcpLspServerHostFactory(); this.activeServers = new ConcurrentHashMap<>(); } @Override - public LspServerHandle bootServer(final LspServerBootRequest request) { - final LspServerBootRequest safeRequest = Objects.requireNonNull(request, "request"); - final ProjectScopedLspServerHost host = serverHostFactory.create(safeRequest, compilerBridge); - final ProjectScopedLspServerHost previous = activeServers.putIfAbsent(safeRequest.project().projectKey(), host); + public void bootServer(final LspServerConfiguration serverConfiguration, LspProjectContext context) { + final var host = serverHostFactory.create(serverConfiguration, context, compilerBridge); + final var previous = activeServers.putIfAbsent(context.projectKey(), host); if (previous != null) { - throw new IllegalStateException("LSP server already booted for project " + safeRequest.project().projectKey()); + throw new IllegalStateException("LSP server already booted for project " + context.projectKey()); } try { - final var endpoint = host.start(); - return new LspServerHandle(safeRequest.project(), endpoint); + host.start(); } catch (RuntimeException runtimeException) { - activeServers.remove(safeRequest.project().projectKey(), host); + activeServers.remove(context.projectKey(), host); closeQuietly(host); throw runtimeException; } @@ -46,15 +39,15 @@ public final class LspServerLifecycleImpl implements LspServerLifecycle { @Override public void shutdownServer(final LspProjectContext project) { - final LspProjectContext safeProject = Objects.requireNonNull(project, "project"); - final ProjectScopedLspServerHost host = activeServers.remove(safeProject.projectKey()); + final var safeProject = Objects.requireNonNull(project, "project"); + final var host = activeServers.remove(safeProject.projectKey()); if (host == null) { return; } closeQuietly(host); } - private static void closeQuietly(final ProjectScopedLspServerHost host) { + private static void closeQuietly(final TcpLspServerHost host) { try { host.close(); } catch (Exception exception) { diff --git a/prometeu-lsp/prometeu-lsp-v1/src/main/java/p/studio/lsp/services/host/TcpLspServerHost.java b/prometeu-lsp/prometeu-lsp-v1/src/main/java/p/studio/lsp/services/TcpLspServerHost.java similarity index 74% rename from prometeu-lsp/prometeu-lsp-v1/src/main/java/p/studio/lsp/services/host/TcpLspServerHost.java rename to prometeu-lsp/prometeu-lsp-v1/src/main/java/p/studio/lsp/services/TcpLspServerHost.java index f01a4388..0f7edc60 100644 --- a/prometeu-lsp/prometeu-lsp-v1/src/main/java/p/studio/lsp/services/host/TcpLspServerHost.java +++ b/prometeu-lsp/prometeu-lsp-v1/src/main/java/p/studio/lsp/services/TcpLspServerHost.java @@ -1,10 +1,10 @@ -package p.studio.lsp.services.host; +package p.studio.lsp.services; import org.eclipse.lsp4j.jsonrpc.Launcher; import org.eclipse.lsp4j.launch.LSPLauncher; import org.eclipse.lsp4j.services.LanguageClient; -import p.studio.lsp.messages.LspServerBootRequest; -import p.studio.lsp.messages.LspServerEndpoint; +import p.studio.lsp.messages.LspProjectContext; +import p.studio.lsp.messages.LspServerConfiguration; import p.studio.lsp.services.compiler.CompilerLanguageServiceBridge; import p.studio.lsp.services.protocol.PrometeuLanguageServer; @@ -16,19 +16,21 @@ import java.util.Objects; import java.util.concurrent.ExecutorService; import java.util.concurrent.Executors; -public final class TcpLspServerHost implements ProjectScopedLspServerHost { - private final LspServerBootRequest request; +public final class TcpLspServerHost { + private final LspServerConfiguration serverConfiguration; + private final LspProjectContext context; private final CompilerLanguageServiceBridge compilerBridge; private final ExecutorService clientExecutor; private volatile boolean closed; private volatile ServerSocket serverSocket; private volatile Thread acceptThread; - private volatile LspServerEndpoint endpoint; public TcpLspServerHost( - final LspServerBootRequest request, + final LspServerConfiguration serverConfiguration, + final LspProjectContext context, final CompilerLanguageServiceBridge compilerBridge) { - this.request = Objects.requireNonNull(request, "request"); + this.serverConfiguration = Objects.requireNonNull(serverConfiguration, "serverConfiguration"); + this.context = Objects.requireNonNull(context, "context"); this.compilerBridge = Objects.requireNonNull(compilerBridge, "compilerBridge"); this.clientExecutor = Executors.newCachedThreadPool(runnable -> { final Thread thread = new Thread(runnable); @@ -38,20 +40,16 @@ public final class TcpLspServerHost implements ProjectScopedLspServerHost { }); } - @Override - public synchronized LspServerEndpoint start() { - if (endpoint != null) { - return endpoint; + public synchronized void start() { + if (serverSocket != null) { + return; } try { - final InetAddress bindAddress = InetAddress.getByName(request.configuration().host()); - final ServerSocket socket = new ServerSocket(request.configuration().port(), 50, bindAddress); - serverSocket = socket; - endpoint = new LspServerEndpoint(bindAddress.getHostAddress(), socket.getLocalPort()); + final InetAddress bindAddress = InetAddress.getByName(serverConfiguration.getEndpoint().host()); + serverSocket = new ServerSocket(serverConfiguration.getEndpoint().port(), 50, bindAddress); acceptThread = new Thread(this::acceptLoop, "prometeu-lsp-v1-accept"); acceptThread.setDaemon(true); acceptThread.start(); - return endpoint; } catch (IOException exception) { throw new IllegalStateException("failed to start TCP LSP host", exception); } @@ -72,7 +70,7 @@ public final class TcpLspServerHost implements ProjectScopedLspServerHost { private void handleClient(final Socket socket) { try (socket) { - final var server = new PrometeuLanguageServer(request.project(), compilerBridge); + final var server = new PrometeuLanguageServer(context, compilerBridge); final Launcher launcher = LSPLauncher.createServerLauncher( server, socket.getInputStream(), @@ -84,7 +82,6 @@ public final class TcpLspServerHost implements ProjectScopedLspServerHost { } } - @Override public synchronized void close() throws Exception { if (closed) { return; diff --git a/prometeu-lsp/prometeu-lsp-v1/src/main/java/p/studio/lsp/services/TcpLspServerHostFactory.java b/prometeu-lsp/prometeu-lsp-v1/src/main/java/p/studio/lsp/services/TcpLspServerHostFactory.java new file mode 100644 index 00000000..1aaf9f0f --- /dev/null +++ b/prometeu-lsp/prometeu-lsp-v1/src/main/java/p/studio/lsp/services/TcpLspServerHostFactory.java @@ -0,0 +1,14 @@ +package p.studio.lsp.services; + +import p.studio.lsp.messages.LspProjectContext; +import p.studio.lsp.messages.LspServerConfiguration; +import p.studio.lsp.services.compiler.CompilerLanguageServiceBridge; + +public final class TcpLspServerHostFactory { + public TcpLspServerHost create( + final LspServerConfiguration serverConfiguration, + final LspProjectContext context, + final CompilerLanguageServiceBridge compilerBridge) { + return new TcpLspServerHost(serverConfiguration, context, compilerBridge); + } +} diff --git a/prometeu-lsp/prometeu-lsp-v1/src/main/java/p/studio/lsp/services/compiler/CompilerLanguageServiceBridge.java b/prometeu-lsp/prometeu-lsp-v1/src/main/java/p/studio/lsp/services/compiler/CompilerLanguageServiceBridge.java index 375f5c29..ae4062aa 100644 --- a/prometeu-lsp/prometeu-lsp-v1/src/main/java/p/studio/lsp/services/compiler/CompilerLanguageServiceBridge.java +++ b/prometeu-lsp/prometeu-lsp-v1/src/main/java/p/studio/lsp/services/compiler/CompilerLanguageServiceBridge.java @@ -4,10 +4,11 @@ import p.studio.compiler.workspaces.BuilderPipelineService; import p.studio.lsp.messages.*; import p.studio.lsp.services.LanguageServiceBridge; +import java.util.List; import java.util.Objects; -public final class CompilerLanguageServiceBridge implements LanguageServiceBridge { - private final BuilderPipelineService builderPipelineService; +public record CompilerLanguageServiceBridge( + BuilderPipelineService builderPipelineService) implements LanguageServiceBridge { public CompilerLanguageServiceBridge() { this(BuilderPipelineService.INSTANCE); @@ -17,13 +18,9 @@ public final class CompilerLanguageServiceBridge implements LanguageServiceBridg this.builderPipelineService = Objects.requireNonNull(builderPipelineService, "builderPipelineService"); } - public BuilderPipelineService builderPipelineService() { - return builderPipelineService; - } - @Override - public BaselineServerDescription describeServer(final LspProjectContext project) { - Objects.requireNonNull(project, "project"); + public BaselineServerDescription describeServer(final LspProjectContext context) { + Objects.requireNonNull(context, "context"); return new BaselineServerDescription( "Prometeu Studio LSP", "0.1.0", @@ -32,13 +29,13 @@ public final class CompilerLanguageServiceBridge implements LanguageServiceBridg @Override public BaselineDocumentAnalysis analyzeDocument( - final LspProjectContext project, + final LspProjectContext context, final String documentUri, final String text) { - Objects.requireNonNull(project, "project"); + Objects.requireNonNull(context, "context"); // Wave 1 keeps responses intentionally synthetic while hardening the bridge boundary. final String message = "Compiler-backed baseline via " + builderPipelineService.getClass().getSimpleName(); - return new BaselineDocumentAnalysis(java.util.List.of(new BaselineDocumentIssue( + return new BaselineDocumentAnalysis(List.of(new BaselineDocumentIssue( 0, 0, 0, @@ -50,25 +47,25 @@ public final class CompilerLanguageServiceBridge implements LanguageServiceBridg @Override public BaselineHover hover( - final LspProjectContext project, + final LspProjectContext context, final String documentUri, final int line, final int character) { - Objects.requireNonNull(project, "project"); + Objects.requireNonNull(context, "context"); return new BaselineHover(""" **Prometeu Studio LSP** - + Compiler-backed baseline. - + Semantic enrichment will be layered later. """); } @Override public String onSave( - final LspProjectContext project, + final LspProjectContext context, final String documentUri) { - Objects.requireNonNull(project, "project"); + Objects.requireNonNull(context, "context"); return "Prometeu Studio saw save: " + documentUri; } diff --git a/prometeu-lsp/prometeu-lsp-v1/src/main/java/p/studio/lsp/services/host/ProjectScopedLspServerHost.java b/prometeu-lsp/prometeu-lsp-v1/src/main/java/p/studio/lsp/services/host/ProjectScopedLspServerHost.java deleted file mode 100644 index a5263266..00000000 --- a/prometeu-lsp/prometeu-lsp-v1/src/main/java/p/studio/lsp/services/host/ProjectScopedLspServerHost.java +++ /dev/null @@ -1,10 +0,0 @@ -package p.studio.lsp.services.host; - -import p.studio.lsp.messages.LspServerEndpoint; - -public interface ProjectScopedLspServerHost extends AutoCloseable { - LspServerEndpoint start(); - - @Override - void close() throws Exception; -} diff --git a/prometeu-lsp/prometeu-lsp-v1/src/main/java/p/studio/lsp/services/host/ProjectScopedLspServerHostFactory.java b/prometeu-lsp/prometeu-lsp-v1/src/main/java/p/studio/lsp/services/host/ProjectScopedLspServerHostFactory.java deleted file mode 100644 index 130c764e..00000000 --- a/prometeu-lsp/prometeu-lsp-v1/src/main/java/p/studio/lsp/services/host/ProjectScopedLspServerHostFactory.java +++ /dev/null @@ -1,10 +0,0 @@ -package p.studio.lsp.services.host; - -import p.studio.lsp.messages.LspServerBootRequest; -import p.studio.lsp.services.compiler.CompilerLanguageServiceBridge; - -public interface ProjectScopedLspServerHostFactory { - ProjectScopedLspServerHost create( - LspServerBootRequest request, - CompilerLanguageServiceBridge compilerBridge); -} diff --git a/prometeu-lsp/prometeu-lsp-v1/src/main/java/p/studio/lsp/services/host/TcpLspServerHostFactory.java b/prometeu-lsp/prometeu-lsp-v1/src/main/java/p/studio/lsp/services/host/TcpLspServerHostFactory.java deleted file mode 100644 index 465d5f7e..00000000 --- a/prometeu-lsp/prometeu-lsp-v1/src/main/java/p/studio/lsp/services/host/TcpLspServerHostFactory.java +++ /dev/null @@ -1,13 +0,0 @@ -package p.studio.lsp.services.host; - -import p.studio.lsp.messages.LspServerBootRequest; -import p.studio.lsp.services.compiler.CompilerLanguageServiceBridge; - -public final class TcpLspServerHostFactory implements ProjectScopedLspServerHostFactory { - @Override - public ProjectScopedLspServerHost create( - final LspServerBootRequest request, - final CompilerLanguageServiceBridge compilerBridge) { - return new TcpLspServerHost(request, compilerBridge); - } -} diff --git a/prometeu-lsp/prometeu-lsp-v1/src/test/java/p/studio/lsp/services/LspServerLifecycleImplTest.java b/prometeu-lsp/prometeu-lsp-v1/src/test/java/p/studio/lsp/services/LspServerLifecycleImplTest.java deleted file mode 100644 index 6d71a5f7..00000000 --- a/prometeu-lsp/prometeu-lsp-v1/src/test/java/p/studio/lsp/services/LspServerLifecycleImplTest.java +++ /dev/null @@ -1,63 +0,0 @@ -package p.studio.lsp.services; - -import org.junit.jupiter.api.Test; -import p.studio.lsp.messages.LspProjectContext; -import p.studio.lsp.messages.LspServerBootRequest; -import p.studio.lsp.messages.LspServerEndpoint; -import p.studio.lsp.services.compiler.CompilerLanguageServiceBridge; -import p.studio.lsp.services.host.ProjectScopedLspServerHost; -import p.studio.lsp.services.host.ProjectScopedLspServerHostFactory; - -import java.nio.file.Path; - -import static org.junit.jupiter.api.Assertions.assertEquals; -import static org.junit.jupiter.api.Assertions.assertThrows; -import static org.junit.jupiter.api.Assertions.assertTrue; - -class LspServerLifecycleImplTest { - - @Test - void lifecycleBootsAndShutsDownProjectScopedHost() { - final FakeHost host = new FakeHost(); - final ProjectScopedLspServerHostFactory factory = (request, compilerBridge) -> host; - final var lifecycle = new LspServerLifecycleImpl(factory, new CompilerLanguageServiceBridge()); - final var project = new LspProjectContext("demo", "pbs", Path.of(".")); - - final var handle = lifecycle.bootServer(LspServerBootRequest.defaults(project)); - - assertEquals(project, handle.project()); - assertEquals("127.0.0.1", handle.endpoint().host()); - assertEquals(7777, handle.endpoint().port()); - assertTrue(host.started); - - lifecycle.shutdownServer(project); - assertTrue(host.closed); - } - - @Test - void lifecycleRejectsDoubleBootForSameProject() { - final ProjectScopedLspServerHostFactory factory = (request, compilerBridge) -> new FakeHost(); - final var lifecycle = new LspServerLifecycleImpl(factory, new CompilerLanguageServiceBridge()); - final var request = LspServerBootRequest.defaults(new LspProjectContext("demo", "pbs", Path.of("."))); - - lifecycle.bootServer(request); - - assertThrows(IllegalStateException.class, () -> lifecycle.bootServer(request)); - } - - private static final class FakeHost implements ProjectScopedLspServerHost { - private boolean started; - private boolean closed; - - @Override - public LspServerEndpoint start() { - started = true; - return new LspServerEndpoint("127.0.0.1", 7777); - } - - @Override - public void close() { - closed = true; - } - } -} diff --git a/prometeu-lsp/prometeu-lsp-v1/src/test/java/p/studio/lsp/services/boundary/LspV1BoundaryTest.java b/prometeu-lsp/prometeu-lsp-v1/src/test/java/p/studio/lsp/services/boundary/LspV1BoundaryTest.java deleted file mode 100644 index 2b09e71d..00000000 --- a/prometeu-lsp/prometeu-lsp-v1/src/test/java/p/studio/lsp/services/boundary/LspV1BoundaryTest.java +++ /dev/null @@ -1,46 +0,0 @@ -package p.studio.lsp.services.boundary; - -import org.junit.jupiter.api.Test; - -import java.io.IOException; -import java.nio.file.Files; -import java.nio.file.Path; -import java.util.List; - -import static org.junit.jupiter.api.Assertions.assertFalse; -import static org.junit.jupiter.api.Assertions.assertTrue; - -class LspV1BoundaryTest { - - @Test - void lsp4jMustRemainContainedInsideLspV1Sources() throws IOException { - final List forbiddenRoots = List.of( - Path.of("../prometeu-lsp-api/src/main/java"), - Path.of("../../../prometeu-studio/src/main/java"), - Path.of("../../../prometeu-app/src/main/java"), - Path.of("../../../prometeu-compiler"), - Path.of("../../../prometeu-packer"), - Path.of("../../../prometeu-infra")); - - for (final Path root : forbiddenRoots) { - assertNoLsp4jImports(root.normalize()); - } - } - - private static void assertNoLsp4jImports(final Path root) throws IOException { - if (!Files.exists(root)) { - return; - } - final List javaFiles; - try (var stream = Files.walk(root)) { - javaFiles = stream - .filter(path -> path.toString().endsWith(".java")) - .toList(); - } - - for (final Path javaFile : javaFiles) { - final String source = Files.readString(javaFile); - assertFalse(source.contains("org.eclipse.lsp4j"), () -> "LSP4J leaked outside lsp-v1: " + javaFile); - } - } -} diff --git a/prometeu-lsp/prometeu-lsp-v1/src/test/java/p/studio/lsp/services/compiler/CompilerLanguageServiceBridgeTest.java b/prometeu-lsp/prometeu-lsp-v1/src/test/java/p/studio/lsp/services/compiler/CompilerLanguageServiceBridgeTest.java deleted file mode 100644 index 56c0735d..00000000 --- a/prometeu-lsp/prometeu-lsp-v1/src/test/java/p/studio/lsp/services/compiler/CompilerLanguageServiceBridgeTest.java +++ /dev/null @@ -1,32 +0,0 @@ -package p.studio.lsp.services.compiler; - -import org.junit.jupiter.api.Test; -import p.studio.lsp.messages.BaselineDocumentAnalysis; -import p.studio.lsp.messages.BaselineHover; -import p.studio.lsp.messages.BaselineServerDescription; -import p.studio.lsp.messages.LspProjectContext; - -import java.nio.file.Path; - -import static org.junit.jupiter.api.Assertions.assertEquals; -import static org.junit.jupiter.api.Assertions.assertFalse; -import static org.junit.jupiter.api.Assertions.assertTrue; - -class CompilerLanguageServiceBridgeTest { - - @Test - void bridgeProvidesStableBaselineResponses() { - final CompilerLanguageServiceBridge bridge = new CompilerLanguageServiceBridge(); - final LspProjectContext project = new LspProjectContext("demo", "pbs", Path.of(".")); - - final BaselineServerDescription server = bridge.describeServer(project); - final BaselineDocumentAnalysis analysis = bridge.analyzeDocument(project, "file:///demo.pbs", "let x = 1"); - final BaselineHover hover = bridge.hover(project, "file:///demo.pbs", 0, 0); - - assertEquals("Prometeu Studio LSP", server.name()); - assertTrue(server.hoverSupported()); - assertFalse(analysis.issues().isEmpty()); - assertTrue(analysis.issues().getFirst().message().contains("BuilderPipelineService")); - assertTrue(hover.markdown().contains("Compiler-backed baseline")); - } -} diff --git a/prometeu-lsp/prometeu-lsp-v1/src/test/java/p/studio/lsp/services/protocol/PrometeuLanguageServerTest.java b/prometeu-lsp/prometeu-lsp-v1/src/test/java/p/studio/lsp/services/protocol/PrometeuLanguageServerTest.java deleted file mode 100644 index 66db3f0a..00000000 --- a/prometeu-lsp/prometeu-lsp-v1/src/test/java/p/studio/lsp/services/protocol/PrometeuLanguageServerTest.java +++ /dev/null @@ -1,175 +0,0 @@ -package p.studio.lsp.services.protocol; - -import org.eclipse.lsp4j.InitializeParams; -import org.eclipse.lsp4j.InitializeResult; -import org.eclipse.lsp4j.WorkspaceFolder; -import org.eclipse.lsp4j.jsonrpc.ResponseErrorException; -import org.eclipse.lsp4j.PublishDiagnosticsParams; -import org.eclipse.lsp4j.services.TextDocumentService; -import org.junit.jupiter.api.Test; -import p.studio.lsp.messages.BaselineDocumentAnalysis; -import p.studio.lsp.messages.BaselineHover; -import p.studio.lsp.messages.BaselineServerDescription; -import p.studio.lsp.messages.LspProjectContext; -import p.studio.lsp.services.LanguageServiceBridge; -import p.studio.lsp.services.protocol.mapping.ProtocolMessageMapper; - -import java.nio.file.Path; -import java.util.List; -import java.util.concurrent.CompletionException; - -import static org.junit.jupiter.api.Assertions.assertEquals; -import static org.junit.jupiter.api.Assertions.assertInstanceOf; -import static org.junit.jupiter.api.Assertions.assertSame; -import static org.junit.jupiter.api.Assertions.assertTrue; - -class PrometeuLanguageServerTest { - - @Test - void initializeDelegatesThroughBridgeAndMapper() { - final RecordingBridge bridge = new RecordingBridge(); - final RecordingMapper mapper = new RecordingMapper(); - final InitializeResult expected = new InitializeResult(); - mapper.initializeResult = expected; - - final PrometeuLanguageServer server = new PrometeuLanguageServer( - new LspProjectContext("demo", "pbs", Path.of(".")), - bridge, - mapper, - new NoopTextDocumentService(), - new PrometeuWorkspaceService()); - - final InitializeParams params = new InitializeParams(); - params.setRootUri(Path.of(".").toAbsolutePath().normalize().toUri().toString()); - - final InitializeResult result = server.initialize(params).join(); - - assertSame(expected, result); - assertEquals(1, bridge.describeServerCalls); - assertSame(bridge.serverDescription, mapper.lastServerDescription); - } - - @Test - void initializeRejectsClientBoundToDifferentProjectRoot() { - final RecordingBridge bridge = new RecordingBridge(); - final RecordingMapper mapper = new RecordingMapper(); - final PrometeuLanguageServer server = new PrometeuLanguageServer( - new LspProjectContext("demo", "pbs", Path.of("/tmp/studio-project")), - bridge, - mapper, - new NoopTextDocumentService(), - new PrometeuWorkspaceService()); - - final InitializeParams params = new InitializeParams(); - params.setRootUri(Path.of("/tmp/another-project").toUri().toString()); - - final CompletionException failure = org.junit.jupiter.api.Assertions.assertThrows( - CompletionException.class, - () -> server.initialize(params).join()); - - final ResponseErrorException responseError = assertInstanceOf(ResponseErrorException.class, failure.getCause()); - assertTrue(responseError.getMessage().contains("/tmp/studio-project")); - assertEquals(0, bridge.describeServerCalls); - } - - @Test - void initializeAcceptsMatchingWorkspaceFolder() { - final RecordingBridge bridge = new RecordingBridge(); - final RecordingMapper mapper = new RecordingMapper(); - mapper.initializeResult = new InitializeResult(); - final Path projectRoot = Path.of("/tmp/studio-project").toAbsolutePath().normalize(); - final PrometeuLanguageServer server = new PrometeuLanguageServer( - new LspProjectContext("demo", "pbs", projectRoot), - bridge, - mapper, - new NoopTextDocumentService(), - new PrometeuWorkspaceService()); - - final InitializeParams params = new InitializeParams(); - params.setWorkspaceFolders(List.of(new WorkspaceFolder(projectRoot.toUri().toString(), "studio-project"))); - - server.initialize(params).join(); - - assertEquals(1, bridge.describeServerCalls); - } - - private static final class RecordingBridge implements LanguageServiceBridge { - private int describeServerCalls; - private final BaselineServerDescription serverDescription = new BaselineServerDescription("demo", "1", true); - - @Override - public BaselineServerDescription describeServer(final LspProjectContext project) { - describeServerCalls++; - return serverDescription; - } - - @Override - public BaselineDocumentAnalysis analyzeDocument(final LspProjectContext project, final String documentUri, final String text) { - return new BaselineDocumentAnalysis(List.of()); - } - - @Override - public BaselineHover hover(final LspProjectContext project, final String documentUri, final int line, final int character) { - return new BaselineHover("hover"); - } - - @Override - public String onSave(final LspProjectContext project, final String documentUri) { - return "saved"; - } - } - - private static final class RecordingMapper implements ProtocolMessageMapper { - private InitializeResult initializeResult; - private BaselineServerDescription lastServerDescription; - - @Override - public InitializeResult mapInitializeResult(final BaselineServerDescription description) { - lastServerDescription = description; - return initializeResult; - } - - @Override - public PublishDiagnosticsParams mapDiagnostics(final String uri, final BaselineDocumentAnalysis analysis) { - throw new UnsupportedOperationException(); - } - - @Override - public PublishDiagnosticsParams emptyDiagnostics(final String uri) { - throw new UnsupportedOperationException(); - } - - @Override - public org.eclipse.lsp4j.Hover mapHover(final BaselineHover hover) { - throw new UnsupportedOperationException(); - } - - @Override - public org.eclipse.lsp4j.MessageParams mapInfoMessage(final String message) { - return new org.eclipse.lsp4j.MessageParams(); - } - - @Override - public org.eclipse.lsp4j.MessageParams mapErrorMessage(final String message) { - return new org.eclipse.lsp4j.MessageParams(); - } - } - - private static final class NoopTextDocumentService implements TextDocumentService { - @Override - public void didOpen(final org.eclipse.lsp4j.DidOpenTextDocumentParams params) { - } - - @Override - public void didChange(final org.eclipse.lsp4j.DidChangeTextDocumentParams params) { - } - - @Override - public void didClose(final org.eclipse.lsp4j.DidCloseTextDocumentParams params) { - } - - @Override - public void didSave(final org.eclipse.lsp4j.DidSaveTextDocumentParams params) { - } - } -} diff --git a/prometeu-lsp/prometeu-lsp-v1/src/test/java/p/studio/lsp/services/protocol/PrometeuTextDocumentServiceTest.java b/prometeu-lsp/prometeu-lsp-v1/src/test/java/p/studio/lsp/services/protocol/PrometeuTextDocumentServiceTest.java deleted file mode 100644 index 3deccbd5..00000000 --- a/prometeu-lsp/prometeu-lsp-v1/src/test/java/p/studio/lsp/services/protocol/PrometeuTextDocumentServiceTest.java +++ /dev/null @@ -1,141 +0,0 @@ -package p.studio.lsp.services.protocol; - -import org.eclipse.lsp4j.*; -import org.eclipse.lsp4j.services.LanguageClient; -import org.junit.jupiter.api.Test; -import p.studio.lsp.messages.*; -import p.studio.lsp.services.LanguageServiceBridge; -import p.studio.lsp.services.protocol.mapping.ProtocolMessageMapper; - -import java.nio.file.Path; -import java.util.List; -import java.util.concurrent.CompletableFuture; - -import static org.junit.jupiter.api.Assertions.assertEquals; -import static org.junit.jupiter.api.Assertions.assertSame; - -class PrometeuTextDocumentServiceTest { - - @Test - void documentEventsDelegateToBridgeAndMapper() { - final RecordingBridge bridge = new RecordingBridge(); - final RecordingMapper mapper = new RecordingMapper(); - final RecordingClient client = new RecordingClient(); - final PrometeuTextDocumentService service = new PrometeuTextDocumentService( - new LspProjectContext("demo", "pbs", Path.of(".")), - bridge, - mapper); - service.connect(client); - - service.didOpen(new DidOpenTextDocumentParams(new TextDocumentItem("file:///demo.pbs", "pbs", 1, "abc"))); - service.didSave(new DidSaveTextDocumentParams(new TextDocumentIdentifier("file:///demo.pbs"), "abc")); - service.hover(new HoverParams(new TextDocumentIdentifier("file:///demo.pbs"), new Position(0, 0))).join(); - - assertEquals(1, bridge.analyzeCalls); - assertEquals(1, bridge.saveCalls); - assertEquals(1, bridge.hoverCalls); - assertSame(bridge.lastAnalysis, mapper.lastAnalysis); - assertSame(bridge.lastHover, mapper.lastHover); - assertSame(mapper.diagnostics, client.lastDiagnostics); - assertSame(mapper.infoMessage, client.lastLogMessage); - } - - private static final class RecordingBridge implements LanguageServiceBridge { - private int analyzeCalls; - private int saveCalls; - private int hoverCalls; - private final BaselineDocumentAnalysis lastAnalysis = new BaselineDocumentAnalysis(List.of( - new BaselineDocumentIssue(0, 0, 0, 1, BaselineIssueSeverity.INFORMATION, "src", "msg"))); - private final BaselineHover lastHover = new BaselineHover("hover"); - - @Override - public BaselineServerDescription describeServer(final LspProjectContext project) { - return new BaselineServerDescription("demo", "1", true); - } - - @Override - public BaselineDocumentAnalysis analyzeDocument(final LspProjectContext project, final String documentUri, final String text) { - analyzeCalls++; - return lastAnalysis; - } - - @Override - public BaselineHover hover(final LspProjectContext project, final String documentUri, final int line, final int character) { - hoverCalls++; - return lastHover; - } - - @Override - public String onSave(final LspProjectContext project, final String documentUri) { - saveCalls++; - return "saved"; - } - } - - private static final class RecordingMapper implements ProtocolMessageMapper { - private final PublishDiagnosticsParams diagnostics = new PublishDiagnosticsParams("file:///demo.pbs", List.of()); - private final MessageParams infoMessage = new MessageParams(MessageType.Info, "saved"); - private BaselineDocumentAnalysis lastAnalysis; - private BaselineHover lastHover; - - @Override - public InitializeResult mapInitializeResult(final BaselineServerDescription description) { - throw new UnsupportedOperationException(); - } - - @Override - public PublishDiagnosticsParams mapDiagnostics(final String uri, final BaselineDocumentAnalysis analysis) { - lastAnalysis = analysis; - return diagnostics; - } - - @Override - public PublishDiagnosticsParams emptyDiagnostics(final String uri) { - return new PublishDiagnosticsParams(uri, List.of()); - } - - @Override - public Hover mapHover(final BaselineHover hover) { - lastHover = hover; - return new Hover(); - } - - @Override - public MessageParams mapInfoMessage(final String message) { - return infoMessage; - } - - @Override - public MessageParams mapErrorMessage(final String message) { - return infoMessage; - } - } - - private static final class RecordingClient implements LanguageClient { - private PublishDiagnosticsParams lastDiagnostics; - private MessageParams lastLogMessage; - - @Override - public void telemetryEvent(final Object object) { - } - - @Override - public void publishDiagnostics(final PublishDiagnosticsParams diagnostics) { - lastDiagnostics = diagnostics; - } - - @Override - public void showMessage(final MessageParams messageParams) { - } - - @Override - public CompletableFuture showMessageRequest(final ShowMessageRequestParams requestParams) { - return CompletableFuture.completedFuture(null); - } - - @Override - public void logMessage(final MessageParams message) { - lastLogMessage = message; - } - } -} diff --git a/prometeu-studio/src/main/java/p/studio/projects/ProjectReference.java b/prometeu-studio/src/main/java/p/studio/projects/ProjectReference.java index 20e7fb84..32f881b6 100644 --- a/prometeu-studio/src/main/java/p/studio/projects/ProjectReference.java +++ b/prometeu-studio/src/main/java/p/studio/projects/ProjectReference.java @@ -2,6 +2,7 @@ package p.studio.projects; import org.apache.commons.lang3.StringUtils; import p.packer.messages.PackerProjectContext; +import p.studio.lsp.messages.LspProjectContext; import java.nio.file.Path; @@ -35,4 +36,11 @@ public record ProjectReference( public PackerProjectContext toPackerProjectContext() { return new PackerProjectContext(name, absoluteRootPath()); } + + public LspProjectContext toLspProjectContext() { + return new LspProjectContext( + rootPath().toAbsolutePath().normalize().toString(), + languageId(), + rootPath()); + } } diff --git a/prometeu-studio/src/main/java/p/studio/projectsessions/StudioProjectSession.java b/prometeu-studio/src/main/java/p/studio/projectsessions/StudioProjectSession.java index 037e06ef..107c344a 100644 --- a/prometeu-studio/src/main/java/p/studio/projectsessions/StudioProjectSession.java +++ b/prometeu-studio/src/main/java/p/studio/projectsessions/StudioProjectSession.java @@ -1,13 +1,11 @@ package p.studio.projectsessions; import p.studio.execution.StudioExecutionSessionService; -import p.studio.lsp.messages.LspProjectContext; -import p.studio.lsp.messages.LspServerHandle; import p.studio.lsp.api.LspServerLifecycle; +import p.studio.projects.ProjectReference; import p.studio.projectstate.ProjectLocalStudioSetup; import p.studio.projectstate.ProjectLocalStudioState; import p.studio.projectstate.ProjectLocalStudioStateService; -import p.studio.projects.ProjectReference; import java.util.Objects; @@ -17,7 +15,6 @@ public final class StudioProjectSession implements AutoCloseable { private final ProjectLocalStudioSetup projectLocalStudioSetup; private final StudioExecutionSessionService executionSessionService; private final LspServerLifecycle lspServerLifecycle; - private final LspServerHandle lspServerHandle; private ProjectLocalStudioState projectLocalStudioState; private boolean closed; @@ -29,7 +26,6 @@ public final class StudioProjectSession implements AutoCloseable { ProjectLocalStudioSetup.defaults(), new StudioExecutionSessionService(), null, - null, ProjectLocalStudioState.defaults()); } @@ -39,14 +35,12 @@ public final class StudioProjectSession implements AutoCloseable { final ProjectLocalStudioSetup projectLocalStudioSetup, final StudioExecutionSessionService executionSessionService, final LspServerLifecycle lspServerLifecycle, - final LspServerHandle lspServerHandle, final ProjectLocalStudioState projectLocalStudioState) { this.projectReference = Objects.requireNonNull(projectReference, "projectReference"); this.projectLocalStudioStateService = Objects.requireNonNull(projectLocalStudioStateService, "projectLocalStudioStateService"); this.projectLocalStudioSetup = Objects.requireNonNull(projectLocalStudioSetup, "projectLocalStudioSetup"); this.executionSessionService = Objects.requireNonNull(executionSessionService, "executionSessionService"); this.lspServerLifecycle = lspServerLifecycle; - this.lspServerHandle = lspServerHandle; this.projectLocalStudioState = Objects.requireNonNull(projectLocalStudioState, "projectLocalStudioState"); } @@ -66,10 +60,6 @@ public final class StudioProjectSession implements AutoCloseable { return executionSessionService; } - public LspServerHandle lspServerHandle() { - return lspServerHandle; - } - public void replaceProjectLocalStudioState(final ProjectLocalStudioState nextProjectLocalStudioState) { this.projectLocalStudioState = Objects.requireNonNull(nextProjectLocalStudioState, "nextProjectLocalStudioState"); } @@ -106,10 +96,9 @@ public final class StudioProjectSession implements AutoCloseable { } private void shutdownLspServer() { - if (lspServerLifecycle == null || lspServerHandle == null) { + if (lspServerLifecycle == null) { return; } - final LspProjectContext projectContext = lspServerHandle.project(); - lspServerLifecycle.shutdownServer(projectContext); + lspServerLifecycle.shutdownServer(projectReference.toLspProjectContext()); } } diff --git a/prometeu-studio/src/main/java/p/studio/projectsessions/StudioProjectSessionFactory.java b/prometeu-studio/src/main/java/p/studio/projectsessions/StudioProjectSessionFactory.java index dcebf551..2004d2ab 100644 --- a/prometeu-studio/src/main/java/p/studio/projectsessions/StudioProjectSessionFactory.java +++ b/prometeu-studio/src/main/java/p/studio/projectsessions/StudioProjectSessionFactory.java @@ -1,13 +1,11 @@ package p.studio.projectsessions; -import p.studio.lsp.messages.LspProjectContext; -import p.studio.lsp.messages.LspServerBootRequest; -import p.studio.lsp.messages.LspServerHandle; -import p.studio.lsp.api.LspServerLifecycle; import p.studio.execution.StudioExecutionSessionService; +import p.studio.lsp.api.LspServerLifecycle; +import p.studio.lsp.messages.LspServerConfiguration; +import p.studio.projects.ProjectReference; import p.studio.projectstate.ProjectLocalStudioSetupService; import p.studio.projectstate.ProjectLocalStudioStateService; -import p.studio.projects.ProjectReference; import java.util.Objects; @@ -36,22 +34,13 @@ public final class StudioProjectSessionFactory { final ProjectReference target = Objects.requireNonNull(projectReference, "projectReference"); final var setup = projectLocalStudioSetupService.load(target); final var state = projectLocalStudioStateService.load(target); - final LspProjectContext lspProjectContext = toLspProjectContext(target); - final LspServerHandle lspServerHandle = lspServerLifecycle.bootServer(LspServerBootRequest.defaults(lspProjectContext)); + lspServerLifecycle.bootServer(LspServerConfiguration.defaults(), target.toLspProjectContext()); return new StudioProjectSession( target, projectLocalStudioStateService, setup, new StudioExecutionSessionService(), lspServerLifecycle, - lspServerHandle, state); } - - private static LspProjectContext toLspProjectContext(final ProjectReference projectReference) { - return new LspProjectContext( - projectReference.rootPath().toAbsolutePath().normalize().toString(), - projectReference.languageId(), - projectReference.rootPath()); - } } diff --git a/prometeu-studio/src/test/java/p/studio/projectsessions/StudioProjectSessionFactoryTest.java b/prometeu-studio/src/test/java/p/studio/projectsessions/StudioProjectSessionFactoryTest.java index 64cee709..96739885 100644 --- a/prometeu-studio/src/test/java/p/studio/projectsessions/StudioProjectSessionFactoryTest.java +++ b/prometeu-studio/src/test/java/p/studio/projectsessions/StudioProjectSessionFactoryTest.java @@ -1,23 +1,18 @@ package p.studio.projectsessions; import org.junit.jupiter.api.Test; -import p.studio.lsp.messages.LspProjectContext; -import p.studio.lsp.messages.LspServerBootRequest; -import p.studio.lsp.messages.LspServerHandle; import p.studio.lsp.api.LspServerLifecycle; -import p.studio.lsp.messages.LspServerEndpoint; +import p.studio.lsp.messages.LspProjectContext; +import p.studio.lsp.messages.LspServerConfiguration; +import p.studio.projects.ProjectReference; import p.studio.projectstate.ProjectLocalStudioSetup; import p.studio.projectstate.ProjectLocalStudioSetupService; import p.studio.projectstate.ProjectLocalStudioState; import p.studio.projectstate.ProjectLocalStudioStateService; -import p.studio.projects.ProjectReference; import java.nio.file.Path; -import static org.junit.jupiter.api.Assertions.assertEquals; -import static org.junit.jupiter.api.Assertions.assertNotNull; -import static org.junit.jupiter.api.Assertions.assertSame; -import static org.junit.jupiter.api.Assertions.assertThrows; +import static org.junit.jupiter.api.Assertions.*; final class StudioProjectSessionFactoryTest { @Test @@ -44,10 +39,9 @@ final class StudioProjectSessionFactoryTest { assertEquals("IDLE", session.executionSession().snapshot().state().name()); assertSame(projectReference, stateService.loadedProjectReference); assertSame(projectReference, setupService.loadedProjectReference); - assertNotNull(session.lspServerHandle()); assertEquals(1, lspServerLifecycle.bootCalls); - assertEquals(projectReference.languageId(), lspServerLifecycle.lastRequest.project().languageId()); - assertEquals(projectReference.rootPath().toAbsolutePath().normalize(), lspServerLifecycle.lastRequest.project().projectRoot()); + assertEquals(projectReference.languageId(), lspServerLifecycle.lastProjectContext.languageId()); + assertEquals(projectReference.rootPath().toAbsolutePath().normalize(), lspServerLifecycle.lastProjectContext.projectRoot()); } @Test @@ -98,15 +92,12 @@ final class StudioProjectSessionFactoryTest { private static final class RecordingLspServerLifecycle implements LspServerLifecycle { private int bootCalls; - private LspServerBootRequest lastRequest; + private LspProjectContext lastProjectContext; @Override - public LspServerHandle bootServer(final LspServerBootRequest request) { + public void bootServer(LspServerConfiguration serverConfiguration, LspProjectContext context) { bootCalls++; - lastRequest = request; - return new LspServerHandle( - request.project(), - new LspServerEndpoint("127.0.0.1", request.configuration().port())); + lastProjectContext = context; } @Override @@ -116,7 +107,7 @@ final class StudioProjectSessionFactoryTest { private static final class FailingLspServerLifecycle implements LspServerLifecycle { @Override - public LspServerHandle bootServer(final LspServerBootRequest request) { + public void bootServer(LspServerConfiguration serverConfiguration, LspProjectContext context) { throw new IllegalStateException("boom"); } diff --git a/prometeu-studio/src/test/java/p/studio/projectsessions/StudioProjectSessionTest.java b/prometeu-studio/src/test/java/p/studio/projectsessions/StudioProjectSessionTest.java index 39753c34..037f3b83 100644 --- a/prometeu-studio/src/test/java/p/studio/projectsessions/StudioProjectSessionTest.java +++ b/prometeu-studio/src/test/java/p/studio/projectsessions/StudioProjectSessionTest.java @@ -2,15 +2,13 @@ package p.studio.projectsessions; import org.junit.jupiter.api.Test; import p.studio.execution.StudioExecutionSessionService; -import p.studio.lsp.messages.LspProjectContext; -import p.studio.lsp.messages.LspServerHandle; import p.studio.lsp.api.LspServerLifecycle; -import p.studio.lsp.messages.LspServerBootRequest; -import p.studio.lsp.messages.LspServerEndpoint; +import p.studio.lsp.messages.LspProjectContext; +import p.studio.lsp.messages.LspServerConfiguration; +import p.studio.projects.ProjectReference; import p.studio.projectstate.ProjectLocalStudioSetup; import p.studio.projectstate.ProjectLocalStudioState; import p.studio.projectstate.ProjectLocalStudioStateService; -import p.studio.projects.ProjectReference; import java.nio.file.Path; @@ -27,7 +25,6 @@ final class StudioProjectSessionTest { ProjectLocalStudioSetup.defaults(), new StudioExecutionSessionService(), null, - null, ProjectLocalStudioState.defaults()); session.close(); @@ -46,7 +43,6 @@ final class StudioProjectSessionTest { ProjectLocalStudioSetup.defaults(), new StudioExecutionSessionService(), null, - null, ProjectLocalStudioState.defaults()); final ProjectLocalStudioState nextState = ProjectLocalStudioState.defaults() .withOpenShellState(new ProjectLocalStudioState.OpenShellState("ASSETS")); @@ -61,23 +57,18 @@ final class StudioProjectSessionTest { void closeShutsDownLspServerOnlyOnce() { final RecordingProjectLocalStudioStateService stateService = new RecordingProjectLocalStudioStateService(); final RecordingLspServerLifecycle lspServerLifecycle = new RecordingLspServerLifecycle(); - final LspServerHandle lspServerHandle = new LspServerHandle( - new LspProjectContext("demo", "pbs", Path.of("/tmp/example")), - new LspServerEndpoint("127.0.0.1", 7777)); final StudioProjectSession session = new StudioProjectSession( projectReference(), stateService, ProjectLocalStudioSetup.defaults(), new StudioExecutionSessionService(), lspServerLifecycle, - lspServerHandle, ProjectLocalStudioState.defaults()); session.close(); session.close(); assertEquals(1, lspServerLifecycle.shutdownCalls); - assertEquals(lspServerHandle.project(), lspServerLifecycle.lastProject); } private ProjectReference projectReference() { @@ -99,17 +90,15 @@ final class StudioProjectSessionTest { private static final class RecordingLspServerLifecycle implements LspServerLifecycle { private int shutdownCalls; - private LspProjectContext lastProject; @Override - public LspServerHandle bootServer(final LspServerBootRequest request) { + public void bootServer(LspServerConfiguration serverConfiguration, LspProjectContext context) { throw new UnsupportedOperationException(); } @Override public void shutdownServer(final LspProjectContext project) { shutdownCalls++; - lastProject = project; } } } diff --git a/test-projects/main/assets/.prometeu/cache.json b/test-projects/main/assets/.prometeu/cache.json index 0a8c0fad..7d30e3eb 100644 --- a/test-projects/main/assets/.prometeu/cache.json +++ b/test-projects/main/assets/.prometeu/cache.json @@ -24,14 +24,14 @@ "last_modified" : 1774359772403, "fingerprint" : "eeb7cc665386299403b7be1c272375d5077f3647c587f8033aa8c9275f840562", "metadata" : { + "palette" : { + "originalArgb8888" : [ -265674 ], + "convertedRgb565" : [ -122 ] + }, "tile" : { "width" : 32, "height" : 32, "paletteIndices" : "AQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAAAAAAAAAAABAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEAAAAAAAAAAAEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQAAAAAAAAAAAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAAAAAAAAAAABAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEAAAAAAAAAAAEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQAAAAAAAAAAAQEBAQEBAQEBAQEBAAAAAAAAAAAAAAAAAAAAAAAAAAABAQEBAQEBAQEBAQEAAAAAAAAAAAAAAAAAAAAAAAAAAAEBAQEBAQEBAQEBAQAAAAAAAAAAAAAAAAAAAAAAAAAAAQEBAQEBAQEBAQEBAAAAAAAAAAAAAAAAAAAAAAAAAAABAQEBAQEBAQEBAQEAAAAAAAAAAAAAAAAAAAAAAAAAAAEBAQEBAQEBAQEBAQAAAAAAAAAAAAAAAAAAAAAAAAAAAQEBAQEBAQEBAQEBAAAAAAAAAAAAAAAAAAAAAAAAAAABAQEBAQEBAQEBAQEAAAAAAAAAAAAAAAAAAAAAAAAAAAEBAQEBAQEBAQEBAQAAAAAAAAAAAAAAAAAAAQEBAQEBAQEBAQEBAQEBAQEBAAAAAAAAAAAAAAAAAAABAQEBAQEBAQEBAQEBAQEBAQEAAAAAAAAAAAAAAAAAAAEBAQEBAQEBAQEBAQEBAQEBAQAAAAAAAAAAAAAAAAAAAQEBAQEBAQEBAQEBAAAAAAAAAAAAAAAAAAAAAAAAAAABAQEBAQEBAQEBAQEAAAAAAAAAAAAAAAAAAAAAAAAAAAEBAQEBAQEBAQEBAQAAAAAAAAAAAAAAAAAAAQEBAQEBAQEBAQEBAQEBAQEBAAAAAAAAAAAAAAAAAAABAQEBAQEBAQEBAQEBAQEBAQEAAAAAAAAAAAAAAAAAAAEBAQEBAQEBAQEBAQEBAQEBAQAAAAAAAAAAAAAAAAAAAQEBAQEBAQEBAQEBAQEBAQEBAAAAAAAAAAAAAAAAAAABAQEBAQEBAQEBAQEBAQEBAQEAAAAAAAAAAAAAAAAAAAEBAQEBAQEBAQEBAQ==" - }, - "palette" : { - "originalArgb8888" : [ -265674 ], - "convertedRgb565" : [ -122 ] } }, "diagnostics" : [ ] @@ -42,14 +42,14 @@ "last_modified" : 1774359772405, "fingerprint" : "eeb7cc665386299403b7be1c272375d5077f3647c587f8033aa8c9275f840562", "metadata" : { + "palette" : { + "originalArgb8888" : [ -265674 ], + "convertedRgb565" : [ -122 ] + }, "tile" : { "width" : 32, "height" : 32, "paletteIndices" : "AQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAAAAAAAAAAABAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEAAAAAAAAAAAEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQAAAAAAAAAAAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAAAAAAAAAAABAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEAAAAAAAAAAAEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQAAAAAAAAAAAQEBAQEBAQEBAQEBAAAAAAAAAAAAAAAAAAAAAAAAAAABAQEBAQEBAQEBAQEAAAAAAAAAAAAAAAAAAAAAAAAAAAEBAQEBAQEBAQEBAQAAAAAAAAAAAAAAAAAAAAAAAAAAAQEBAQEBAQEBAQEBAAAAAAAAAAAAAAAAAAAAAAAAAAABAQEBAQEBAQEBAQEAAAAAAAAAAAAAAAAAAAAAAAAAAAEBAQEBAQEBAQEBAQAAAAAAAAAAAAAAAAAAAAAAAAAAAQEBAQEBAQEBAQEBAAAAAAAAAAAAAAAAAAAAAAAAAAABAQEBAQEBAQEBAQEAAAAAAAAAAAAAAAAAAAAAAAAAAAEBAQEBAQEBAQEBAQAAAAAAAAAAAAAAAAAAAQEBAQEBAQEBAQEBAQEBAQEBAAAAAAAAAAAAAAAAAAABAQEBAQEBAQEBAQEBAQEBAQEAAAAAAAAAAAAAAAAAAAEBAQEBAQEBAQEBAQEBAQEBAQAAAAAAAAAAAAAAAAAAAQEBAQEBAQEBAQEBAAAAAAAAAAAAAAAAAAAAAAAAAAABAQEBAQEBAQEBAQEAAAAAAAAAAAAAAAAAAAAAAAAAAAEBAQEBAQEBAQEBAQAAAAAAAAAAAAAAAAAAAQEBAQEBAQEBAQEBAQEBAQEBAAAAAAAAAAAAAAAAAAABAQEBAQEBAQEBAQEBAQEBAQEAAAAAAAAAAAAAAAAAAAEBAQEBAQEBAQEBAQEBAQEBAQAAAAAAAAAAAAAAAAAAAQEBAQEBAQEBAQEBAQEBAQEBAAAAAAAAAAAAAAAAAAABAQEBAQEBAQEBAQEBAQEBAQEAAAAAAAAAAAAAAAAAAAEBAQEBAQEBAQEBAQ==" - }, - "palette" : { - "originalArgb8888" : [ -265674 ], - "convertedRgb565" : [ -122 ] } }, "diagnostics" : [ ] @@ -60,14 +60,14 @@ "last_modified" : 1774359772406, "fingerprint" : "eeb7cc665386299403b7be1c272375d5077f3647c587f8033aa8c9275f840562", "metadata" : { + "palette" : { + "originalArgb8888" : [ -265674 ], + "convertedRgb565" : [ -122 ] + }, "tile" : { "width" : 32, "height" : 32, "paletteIndices" : "AQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAAAAAAAAAAABAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEAAAAAAAAAAAEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQAAAAAAAAAAAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAAAAAAAAAAABAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEAAAAAAAAAAAEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQAAAAAAAAAAAQEBAQEBAQEBAQEBAAAAAAAAAAAAAAAAAAAAAAAAAAABAQEBAQEBAQEBAQEAAAAAAAAAAAAAAAAAAAAAAAAAAAEBAQEBAQEBAQEBAQAAAAAAAAAAAAAAAAAAAAAAAAAAAQEBAQEBAQEBAQEBAAAAAAAAAAAAAAAAAAAAAAAAAAABAQEBAQEBAQEBAQEAAAAAAAAAAAAAAAAAAAAAAAAAAAEBAQEBAQEBAQEBAQAAAAAAAAAAAAAAAAAAAAAAAAAAAQEBAQEBAQEBAQEBAAAAAAAAAAAAAAAAAAAAAAAAAAABAQEBAQEBAQEBAQEAAAAAAAAAAAAAAAAAAAAAAAAAAAEBAQEBAQEBAQEBAQAAAAAAAAAAAAAAAAAAAQEBAQEBAQEBAQEBAQEBAQEBAAAAAAAAAAAAAAAAAAABAQEBAQEBAQEBAQEBAQEBAQEAAAAAAAAAAAAAAAAAAAEBAQEBAQEBAQEBAQEBAQEBAQAAAAAAAAAAAAAAAAAAAQEBAQEBAQEBAQEBAAAAAAAAAAAAAAAAAAAAAAAAAAABAQEBAQEBAQEBAQEAAAAAAAAAAAAAAAAAAAAAAAAAAAEBAQEBAQEBAQEBAQAAAAAAAAAAAAAAAAAAAQEBAQEBAQEBAQEBAQEBAQEBAAAAAAAAAAAAAAAAAAABAQEBAQEBAQEBAQEBAQEBAQEAAAAAAAAAAAAAAAAAAAEBAQEBAQEBAQEBAQEBAQEBAQAAAAAAAAAAAAAAAAAAAQEBAQEBAQEBAQEBAQEBAQEBAAAAAAAAAAAAAAAAAAABAQEBAQEBAQEBAQEBAQEBAQEAAAAAAAAAAAAAAAAAAAEBAQEBAQEBAQEBAQ==" - }, - "palette" : { - "originalArgb8888" : [ -265674 ], - "convertedRgb565" : [ -122 ] } }, "diagnostics" : [ ] @@ -78,14 +78,14 @@ "last_modified" : 1774359772408, "fingerprint" : "eeb7cc665386299403b7be1c272375d5077f3647c587f8033aa8c9275f840562", "metadata" : { + "palette" : { + "originalArgb8888" : [ -265674 ], + "convertedRgb565" : [ -122 ] + }, "tile" : { "width" : 32, "height" : 32, "paletteIndices" : "AQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAAAAAAAAAAABAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEAAAAAAAAAAAEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQAAAAAAAAAAAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAAAAAAAAAAABAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEAAAAAAAAAAAEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQAAAAAAAAAAAQEBAQEBAQEBAQEBAAAAAAAAAAAAAAAAAAAAAAAAAAABAQEBAQEBAQEBAQEAAAAAAAAAAAAAAAAAAAAAAAAAAAEBAQEBAQEBAQEBAQAAAAAAAAAAAAAAAAAAAAAAAAAAAQEBAQEBAQEBAQEBAAAAAAAAAAAAAAAAAAAAAAAAAAABAQEBAQEBAQEBAQEAAAAAAAAAAAAAAAAAAAAAAAAAAAEBAQEBAQEBAQEBAQAAAAAAAAAAAAAAAAAAAAAAAAAAAQEBAQEBAQEBAQEBAAAAAAAAAAAAAAAAAAAAAAAAAAABAQEBAQEBAQEBAQEAAAAAAAAAAAAAAAAAAAAAAAAAAAEBAQEBAQEBAQEBAQAAAAAAAAAAAAAAAAAAAQEBAQEBAQEBAQEBAQEBAQEBAAAAAAAAAAAAAAAAAAABAQEBAQEBAQEBAQEBAQEBAQEAAAAAAAAAAAAAAAAAAAEBAQEBAQEBAQEBAQEBAQEBAQAAAAAAAAAAAAAAAAAAAQEBAQEBAQEBAQEBAAAAAAAAAAAAAAAAAAAAAAAAAAABAQEBAQEBAQEBAQEAAAAAAAAAAAAAAAAAAAAAAAAAAAEBAQEBAQEBAQEBAQAAAAAAAAAAAAAAAAAAAQEBAQEBAQEBAQEBAQEBAQEBAAAAAAAAAAAAAAAAAAABAQEBAQEBAQEBAQEBAQEBAQEAAAAAAAAAAAAAAAAAAAEBAQEBAQEBAQEBAQEBAQEBAQAAAAAAAAAAAAAAAAAAAQEBAQEBAQEBAQEBAQEBAQEBAAAAAAAAAAAAAAAAAAABAQEBAQEBAQEBAQEBAQEBAQEAAAAAAAAAAAAAAAAAAAEBAQEBAQEBAQEBAQ==" - }, - "palette" : { - "originalArgb8888" : [ -265674 ], - "convertedRgb565" : [ -122 ] } }, "diagnostics" : [ ] @@ -96,14 +96,14 @@ "last_modified" : 1774359772409, "fingerprint" : "eeb7cc665386299403b7be1c272375d5077f3647c587f8033aa8c9275f840562", "metadata" : { + "palette" : { + "originalArgb8888" : [ -265674 ], + "convertedRgb565" : [ -122 ] + }, "tile" : { "width" : 32, "height" : 32, "paletteIndices" : "AQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAAAAAAAAAAABAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEAAAAAAAAAAAEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQAAAAAAAAAAAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAAAAAAAAAAABAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEAAAAAAAAAAAEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQAAAAAAAAAAAQEBAQEBAQEBAQEBAAAAAAAAAAAAAAAAAAAAAAAAAAABAQEBAQEBAQEBAQEAAAAAAAAAAAAAAAAAAAAAAAAAAAEBAQEBAQEBAQEBAQAAAAAAAAAAAAAAAAAAAAAAAAAAAQEBAQEBAQEBAQEBAAAAAAAAAAAAAAAAAAAAAAAAAAABAQEBAQEBAQEBAQEAAAAAAAAAAAAAAAAAAAAAAAAAAAEBAQEBAQEBAQEBAQAAAAAAAAAAAAAAAAAAAAAAAAAAAQEBAQEBAQEBAQEBAAAAAAAAAAAAAAAAAAAAAAAAAAABAQEBAQEBAQEBAQEAAAAAAAAAAAAAAAAAAAAAAAAAAAEBAQEBAQEBAQEBAQAAAAAAAAAAAAAAAAAAAQEBAQEBAQEBAQEBAQEBAQEBAAAAAAAAAAAAAAAAAAABAQEBAQEBAQEBAQEBAQEBAQEAAAAAAAAAAAAAAAAAAAEBAQEBAQEBAQEBAQEBAQEBAQAAAAAAAAAAAAAAAAAAAQEBAQEBAQEBAQEBAAAAAAAAAAAAAAAAAAAAAAAAAAABAQEBAQEBAQEBAQEAAAAAAAAAAAAAAAAAAAAAAAAAAAEBAQEBAQEBAQEBAQAAAAAAAAAAAAAAAAAAAQEBAQEBAQEBAQEBAQEBAQEBAAAAAAAAAAAAAAAAAAABAQEBAQEBAQEBAQEBAQEBAQEAAAAAAAAAAAAAAAAAAAEBAQEBAQEBAQEBAQEBAQEBAQAAAAAAAAAAAAAAAAAAAQEBAQEBAQEBAQEBAQEBAQEBAAAAAAAAAAAAAAAAAAABAQEBAQEBAQEBAQEBAQEBAQEAAAAAAAAAAAAAAAAAAAEBAQEBAQEBAQEBAQ==" - }, - "palette" : { - "originalArgb8888" : [ -265674 ], - "convertedRgb565" : [ -122 ] } }, "diagnostics" : [ ] @@ -114,14 +114,14 @@ "last_modified" : 1774359772411, "fingerprint" : "eeb7cc665386299403b7be1c272375d5077f3647c587f8033aa8c9275f840562", "metadata" : { + "palette" : { + "originalArgb8888" : [ -265674 ], + "convertedRgb565" : [ -122 ] + }, "tile" : { "width" : 32, "height" : 32, "paletteIndices" : "AQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAAAAAAAAAAABAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEAAAAAAAAAAAEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQAAAAAAAAAAAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAAAAAAAAAAABAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEAAAAAAAAAAAEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQAAAAAAAAAAAQEBAQEBAQEBAQEBAAAAAAAAAAAAAAAAAAAAAAAAAAABAQEBAQEBAQEBAQEAAAAAAAAAAAAAAAAAAAAAAAAAAAEBAQEBAQEBAQEBAQAAAAAAAAAAAAAAAAAAAAAAAAAAAQEBAQEBAQEBAQEBAAAAAAAAAAAAAAAAAAAAAAAAAAABAQEBAQEBAQEBAQEAAAAAAAAAAAAAAAAAAAAAAAAAAAEBAQEBAQEBAQEBAQAAAAAAAAAAAAAAAAAAAAAAAAAAAQEBAQEBAQEBAQEBAAAAAAAAAAAAAAAAAAAAAAAAAAABAQEBAQEBAQEBAQEAAAAAAAAAAAAAAAAAAAAAAAAAAAEBAQEBAQEBAQEBAQAAAAAAAAAAAAAAAAAAAQEBAQEBAQEBAQEBAQEBAQEBAAAAAAAAAAAAAAAAAAABAQEBAQEBAQEBAQEBAQEBAQEAAAAAAAAAAAAAAAAAAAEBAQEBAQEBAQEBAQEBAQEBAQAAAAAAAAAAAAAAAAAAAQEBAQEBAQEBAQEBAAAAAAAAAAAAAAAAAAAAAAAAAAABAQEBAQEBAQEBAQEAAAAAAAAAAAAAAAAAAAAAAAAAAAEBAQEBAQEBAQEBAQAAAAAAAAAAAAAAAAAAAQEBAQEBAQEBAQEBAQEBAQEBAAAAAAAAAAAAAAAAAAABAQEBAQEBAQEBAQEBAQEBAQEAAAAAAAAAAAAAAAAAAAEBAQEBAQEBAQEBAQEBAQEBAQAAAAAAAAAAAAAAAAAAAQEBAQEBAQEBAQEBAQEBAQEBAAAAAAAAAAAAAAAAAAABAQEBAQEBAQEBAQEBAQEBAQEAAAAAAAAAAAAAAAAAAAEBAQEBAQEBAQEBAQ==" - }, - "palette" : { - "originalArgb8888" : [ -265674 ], - "convertedRgb565" : [ -122 ] } }, "diagnostics" : [ ] @@ -132,14 +132,14 @@ "last_modified" : 1774359772412, "fingerprint" : "eeb7cc665386299403b7be1c272375d5077f3647c587f8033aa8c9275f840562", "metadata" : { + "palette" : { + "originalArgb8888" : [ -265674 ], + "convertedRgb565" : [ -122 ] + }, "tile" : { "width" : 32, "height" : 32, "paletteIndices" : "AQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAAAAAAAAAAABAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEAAAAAAAAAAAEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQAAAAAAAAAAAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAAAAAAAAAAABAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEAAAAAAAAAAAEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQAAAAAAAAAAAQEBAQEBAQEBAQEBAAAAAAAAAAAAAAAAAAAAAAAAAAABAQEBAQEBAQEBAQEAAAAAAAAAAAAAAAAAAAAAAAAAAAEBAQEBAQEBAQEBAQAAAAAAAAAAAAAAAAAAAAAAAAAAAQEBAQEBAQEBAQEBAAAAAAAAAAAAAAAAAAAAAAAAAAABAQEBAQEBAQEBAQEAAAAAAAAAAAAAAAAAAAAAAAAAAAEBAQEBAQEBAQEBAQAAAAAAAAAAAAAAAAAAAAAAAAAAAQEBAQEBAQEBAQEBAAAAAAAAAAAAAAAAAAAAAAAAAAABAQEBAQEBAQEBAQEAAAAAAAAAAAAAAAAAAAAAAAAAAAEBAQEBAQEBAQEBAQAAAAAAAAAAAAAAAAAAAQEBAQEBAQEBAQEBAQEBAQEBAAAAAAAAAAAAAAAAAAABAQEBAQEBAQEBAQEBAQEBAQEAAAAAAAAAAAAAAAAAAAEBAQEBAQEBAQEBAQEBAQEBAQAAAAAAAAAAAAAAAAAAAQEBAQEBAQEBAQEBAAAAAAAAAAAAAAAAAAAAAAAAAAABAQEBAQEBAQEBAQEAAAAAAAAAAAAAAAAAAAAAAAAAAAEBAQEBAQEBAQEBAQAAAAAAAAAAAAAAAAAAAQEBAQEBAQEBAQEBAQEBAQEBAAAAAAAAAAAAAAAAAAABAQEBAQEBAQEBAQEBAQEBAQEAAAAAAAAAAAAAAAAAAAEBAQEBAQEBAQEBAQEBAQEBAQAAAAAAAAAAAAAAAAAAAQEBAQEBAQEBAQEBAQEBAQEBAAAAAAAAAAAAAAAAAAABAQEBAQEBAQEBAQEBAQEBAQEAAAAAAAAAAAAAAAAAAAEBAQEBAQEBAQEBAQ==" - }, - "palette" : { - "originalArgb8888" : [ -265674 ], - "convertedRgb565" : [ -122 ] } }, "diagnostics" : [ ] @@ -150,14 +150,14 @@ "last_modified" : 1774359772413, "fingerprint" : "eeb7cc665386299403b7be1c272375d5077f3647c587f8033aa8c9275f840562", "metadata" : { + "palette" : { + "originalArgb8888" : [ -265674 ], + "convertedRgb565" : [ -122 ] + }, "tile" : { "width" : 32, "height" : 32, "paletteIndices" : "AQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAAAAAAAAAAABAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEAAAAAAAAAAAEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQAAAAAAAAAAAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAAAAAAAAAAABAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEAAAAAAAAAAAEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQAAAAAAAAAAAQEBAQEBAQEBAQEBAAAAAAAAAAAAAAAAAAAAAAAAAAABAQEBAQEBAQEBAQEAAAAAAAAAAAAAAAAAAAAAAAAAAAEBAQEBAQEBAQEBAQAAAAAAAAAAAAAAAAAAAAAAAAAAAQEBAQEBAQEBAQEBAAAAAAAAAAAAAAAAAAAAAAAAAAABAQEBAQEBAQEBAQEAAAAAAAAAAAAAAAAAAAAAAAAAAAEBAQEBAQEBAQEBAQAAAAAAAAAAAAAAAAAAAAAAAAAAAQEBAQEBAQEBAQEBAAAAAAAAAAAAAAAAAAAAAAAAAAABAQEBAQEBAQEBAQEAAAAAAAAAAAAAAAAAAAAAAAAAAAEBAQEBAQEBAQEBAQAAAAAAAAAAAAAAAAAAAQEBAQEBAQEBAQEBAQEBAQEBAAAAAAAAAAAAAAAAAAABAQEBAQEBAQEBAQEBAQEBAQEAAAAAAAAAAAAAAAAAAAEBAQEBAQEBAQEBAQEBAQEBAQAAAAAAAAAAAAAAAAAAAQEBAQEBAQEBAQEBAAAAAAAAAAAAAAAAAAAAAAAAAAABAQEBAQEBAQEBAQEAAAAAAAAAAAAAAAAAAAAAAAAAAAEBAQEBAQEBAQEBAQAAAAAAAAAAAAAAAAAAAQEBAQEBAQEBAQEBAQEBAQEBAAAAAAAAAAAAAAAAAAABAQEBAQEBAQEBAQEBAQEBAQEAAAAAAAAAAAAAAAAAAAEBAQEBAQEBAQEBAQEBAQEBAQAAAAAAAAAAAAAAAAAAAQEBAQEBAQEBAQEBAQEBAQEBAAAAAAAAAAAAAAAAAAABAQEBAQEBAQEBAQEBAQEBAQEAAAAAAAAAAAAAAAAAAAEBAQEBAQEBAQEBAQ==" - }, - "palette" : { - "originalArgb8888" : [ -265674 ], - "convertedRgb565" : [ -122 ] } }, "diagnostics" : [ ] @@ -168,14 +168,14 @@ "last_modified" : 1774359772415, "fingerprint" : "eeb7cc665386299403b7be1c272375d5077f3647c587f8033aa8c9275f840562", "metadata" : { + "palette" : { + "originalArgb8888" : [ -265674 ], + "convertedRgb565" : [ -122 ] + }, "tile" : { "width" : 32, "height" : 32, "paletteIndices" : "AQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAAAAAAAAAAABAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEAAAAAAAAAAAEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQAAAAAAAAAAAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAAAAAAAAAAABAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEAAAAAAAAAAAEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQAAAAAAAAAAAQEBAQEBAQEBAQEBAAAAAAAAAAAAAAAAAAAAAAAAAAABAQEBAQEBAQEBAQEAAAAAAAAAAAAAAAAAAAAAAAAAAAEBAQEBAQEBAQEBAQAAAAAAAAAAAAAAAAAAAAAAAAAAAQEBAQEBAQEBAQEBAAAAAAAAAAAAAAAAAAAAAAAAAAABAQEBAQEBAQEBAQEAAAAAAAAAAAAAAAAAAAAAAAAAAAEBAQEBAQEBAQEBAQAAAAAAAAAAAAAAAAAAAAAAAAAAAQEBAQEBAQEBAQEBAAAAAAAAAAAAAAAAAAAAAAAAAAABAQEBAQEBAQEBAQEAAAAAAAAAAAAAAAAAAAAAAAAAAAEBAQEBAQEBAQEBAQAAAAAAAAAAAAAAAAAAAQEBAQEBAQEBAQEBAQEBAQEBAAAAAAAAAAAAAAAAAAABAQEBAQEBAQEBAQEBAQEBAQEAAAAAAAAAAAAAAAAAAAEBAQEBAQEBAQEBAQEBAQEBAQAAAAAAAAAAAAAAAAAAAQEBAQEBAQEBAQEBAAAAAAAAAAAAAAAAAAAAAAAAAAABAQEBAQEBAQEBAQEAAAAAAAAAAAAAAAAAAAAAAAAAAAEBAQEBAQEBAQEBAQAAAAAAAAAAAAAAAAAAAQEBAQEBAQEBAQEBAQEBAQEBAAAAAAAAAAAAAAAAAAABAQEBAQEBAQEBAQEBAQEBAQEAAAAAAAAAAAAAAAAAAAEBAQEBAQEBAQEBAQEBAQEBAQAAAAAAAAAAAAAAAAAAAQEBAQEBAQEBAQEBAQEBAQEBAAAAAAAAAAAAAAAAAAABAQEBAQEBAQEBAQEBAQEBAQEAAAAAAAAAAAAAAAAAAAEBAQEBAQEBAQEBAQ==" - }, - "palette" : { - "originalArgb8888" : [ -265674 ], - "convertedRgb565" : [ -122 ] } }, "diagnostics" : [ ] @@ -186,14 +186,14 @@ "last_modified" : 1774359772416, "fingerprint" : "eeb7cc665386299403b7be1c272375d5077f3647c587f8033aa8c9275f840562", "metadata" : { + "palette" : { + "originalArgb8888" : [ -265674 ], + "convertedRgb565" : [ -122 ] + }, "tile" : { "width" : 32, "height" : 32, "paletteIndices" : "AQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAAAAAAAAAAABAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEAAAAAAAAAAAEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQAAAAAAAAAAAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAAAAAAAAAAABAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEAAAAAAAAAAAEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQAAAAAAAAAAAQEBAQEBAQEBAQEBAAAAAAAAAAAAAAAAAAAAAAAAAAABAQEBAQEBAQEBAQEAAAAAAAAAAAAAAAAAAAAAAAAAAAEBAQEBAQEBAQEBAQAAAAAAAAAAAAAAAAAAAAAAAAAAAQEBAQEBAQEBAQEBAAAAAAAAAAAAAAAAAAAAAAAAAAABAQEBAQEBAQEBAQEAAAAAAAAAAAAAAAAAAAAAAAAAAAEBAQEBAQEBAQEBAQAAAAAAAAAAAAAAAAAAAAAAAAAAAQEBAQEBAQEBAQEBAAAAAAAAAAAAAAAAAAAAAAAAAAABAQEBAQEBAQEBAQEAAAAAAAAAAAAAAAAAAAAAAAAAAAEBAQEBAQEBAQEBAQAAAAAAAAAAAAAAAAAAAQEBAQEBAQEBAQEBAQEBAQEBAAAAAAAAAAAAAAAAAAABAQEBAQEBAQEBAQEBAQEBAQEAAAAAAAAAAAAAAAAAAAEBAQEBAQEBAQEBAQEBAQEBAQAAAAAAAAAAAAAAAAAAAQEBAQEBAQEBAQEBAAAAAAAAAAAAAAAAAAAAAAAAAAABAQEBAQEBAQEBAQEAAAAAAAAAAAAAAAAAAAAAAAAAAAEBAQEBAQEBAQEBAQAAAAAAAAAAAAAAAAAAAQEBAQEBAQEBAQEBAQEBAQEBAAAAAAAAAAAAAAAAAAABAQEBAQEBAQEBAQEBAQEBAQEAAAAAAAAAAAAAAAAAAAEBAQEBAQEBAQEBAQEBAQEBAQAAAAAAAAAAAAAAAAAAAQEBAQEBAQEBAQEBAQEBAQEBAAAAAAAAAAAAAAAAAAABAQEBAQEBAQEBAQEBAQEBAQEAAAAAAAAAAAAAAAAAAAEBAQEBAQEBAQEBAQ==" - }, - "palette" : { - "originalArgb8888" : [ -265674 ], - "convertedRgb565" : [ -122 ] } }, "diagnostics" : [ ] @@ -204,14 +204,14 @@ "last_modified" : 1774359772417, "fingerprint" : "eeb7cc665386299403b7be1c272375d5077f3647c587f8033aa8c9275f840562", "metadata" : { + "palette" : { + "originalArgb8888" : [ -265674 ], + "convertedRgb565" : [ -122 ] + }, "tile" : { "width" : 32, "height" : 32, "paletteIndices" : "AQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAAAAAAAAAAABAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEAAAAAAAAAAAEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQAAAAAAAAAAAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAAAAAAAAAAABAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEAAAAAAAAAAAEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQAAAAAAAAAAAQEBAQEBAQEBAQEBAAAAAAAAAAAAAAAAAAAAAAAAAAABAQEBAQEBAQEBAQEAAAAAAAAAAAAAAAAAAAAAAAAAAAEBAQEBAQEBAQEBAQAAAAAAAAAAAAAAAAAAAAAAAAAAAQEBAQEBAQEBAQEBAAAAAAAAAAAAAAAAAAAAAAAAAAABAQEBAQEBAQEBAQEAAAAAAAAAAAAAAAAAAAAAAAAAAAEBAQEBAQEBAQEBAQAAAAAAAAAAAAAAAAAAAAAAAAAAAQEBAQEBAQEBAQEBAAAAAAAAAAAAAAAAAAAAAAAAAAABAQEBAQEBAQEBAQEAAAAAAAAAAAAAAAAAAAAAAAAAAAEBAQEBAQEBAQEBAQAAAAAAAAAAAAAAAAAAAQEBAQEBAQEBAQEBAQEBAQEBAAAAAAAAAAAAAAAAAAABAQEBAQEBAQEBAQEBAQEBAQEAAAAAAAAAAAAAAAAAAAEBAQEBAQEBAQEBAQEBAQEBAQAAAAAAAAAAAAAAAAAAAQEBAQEBAQEBAQEBAAAAAAAAAAAAAAAAAAAAAAAAAAABAQEBAQEBAQEBAQEAAAAAAAAAAAAAAAAAAAAAAAAAAAEBAQEBAQEBAQEBAQAAAAAAAAAAAAAAAAAAAQEBAQEBAQEBAQEBAQEBAQEBAAAAAAAAAAAAAAAAAAABAQEBAQEBAQEBAQEBAQEBAQEAAAAAAAAAAAAAAAAAAAEBAQEBAQEBAQEBAQEBAQEBAQAAAAAAAAAAAAAAAAAAAQEBAQEBAQEBAQEBAQEBAQEBAAAAAAAAAAAAAAAAAAABAQEBAQEBAQEBAQEBAQEBAQEAAAAAAAAAAAAAAAAAAAEBAQEBAQEBAQEBAQ==" - }, - "palette" : { - "originalArgb8888" : [ -265674 ], - "convertedRgb565" : [ -122 ] } }, "diagnostics" : [ ] @@ -222,14 +222,14 @@ "last_modified" : 1774359772418, "fingerprint" : "eeb7cc665386299403b7be1c272375d5077f3647c587f8033aa8c9275f840562", "metadata" : { + "palette" : { + "originalArgb8888" : [ -265674 ], + "convertedRgb565" : [ -122 ] + }, "tile" : { "width" : 32, "height" : 32, "paletteIndices" : "AQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAAAAAAAAAAABAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEAAAAAAAAAAAEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQAAAAAAAAAAAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAAAAAAAAAAABAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEAAAAAAAAAAAEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQAAAAAAAAAAAQEBAQEBAQEBAQEBAAAAAAAAAAAAAAAAAAAAAAAAAAABAQEBAQEBAQEBAQEAAAAAAAAAAAAAAAAAAAAAAAAAAAEBAQEBAQEBAQEBAQAAAAAAAAAAAAAAAAAAAAAAAAAAAQEBAQEBAQEBAQEBAAAAAAAAAAAAAAAAAAAAAAAAAAABAQEBAQEBAQEBAQEAAAAAAAAAAAAAAAAAAAAAAAAAAAEBAQEBAQEBAQEBAQAAAAAAAAAAAAAAAAAAAAAAAAAAAQEBAQEBAQEBAQEBAAAAAAAAAAAAAAAAAAAAAAAAAAABAQEBAQEBAQEBAQEAAAAAAAAAAAAAAAAAAAAAAAAAAAEBAQEBAQEBAQEBAQAAAAAAAAAAAAAAAAAAAQEBAQEBAQEBAQEBAQEBAQEBAAAAAAAAAAAAAAAAAAABAQEBAQEBAQEBAQEBAQEBAQEAAAAAAAAAAAAAAAAAAAEBAQEBAQEBAQEBAQEBAQEBAQAAAAAAAAAAAAAAAAAAAQEBAQEBAQEBAQEBAAAAAAAAAAAAAAAAAAAAAAAAAAABAQEBAQEBAQEBAQEAAAAAAAAAAAAAAAAAAAAAAAAAAAEBAQEBAQEBAQEBAQAAAAAAAAAAAAAAAAAAAQEBAQEBAQEBAQEBAQEBAQEBAAAAAAAAAAAAAAAAAAABAQEBAQEBAQEBAQEBAQEBAQEAAAAAAAAAAAAAAAAAAAEBAQEBAQEBAQEBAQEBAQEBAQAAAAAAAAAAAAAAAAAAAQEBAQEBAQEBAQEBAQEBAQEBAAAAAAAAAAAAAAAAAAABAQEBAQEBAQEBAQEBAQEBAQEAAAAAAAAAAAAAAAAAAAEBAQEBAQEBAQEBAQ==" - }, - "palette" : { - "originalArgb8888" : [ -265674 ], - "convertedRgb565" : [ -122 ] } }, "diagnostics" : [ ] @@ -240,14 +240,14 @@ "last_modified" : 1774359772420, "fingerprint" : "eeb7cc665386299403b7be1c272375d5077f3647c587f8033aa8c9275f840562", "metadata" : { + "palette" : { + "originalArgb8888" : [ -265674 ], + "convertedRgb565" : [ -122 ] + }, "tile" : { "width" : 32, "height" : 32, "paletteIndices" : "AQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAAAAAAAAAAABAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEAAAAAAAAAAAEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQAAAAAAAAAAAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAAAAAAAAAAABAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEAAAAAAAAAAAEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQAAAAAAAAAAAQEBAQEBAQEBAQEBAAAAAAAAAAAAAAAAAAAAAAAAAAABAQEBAQEBAQEBAQEAAAAAAAAAAAAAAAAAAAAAAAAAAAEBAQEBAQEBAQEBAQAAAAAAAAAAAAAAAAAAAAAAAAAAAQEBAQEBAQEBAQEBAAAAAAAAAAAAAAAAAAAAAAAAAAABAQEBAQEBAQEBAQEAAAAAAAAAAAAAAAAAAAAAAAAAAAEBAQEBAQEBAQEBAQAAAAAAAAAAAAAAAAAAAAAAAAAAAQEBAQEBAQEBAQEBAAAAAAAAAAAAAAAAAAAAAAAAAAABAQEBAQEBAQEBAQEAAAAAAAAAAAAAAAAAAAAAAAAAAAEBAQEBAQEBAQEBAQAAAAAAAAAAAAAAAAAAAQEBAQEBAQEBAQEBAQEBAQEBAAAAAAAAAAAAAAAAAAABAQEBAQEBAQEBAQEBAQEBAQEAAAAAAAAAAAAAAAAAAAEBAQEBAQEBAQEBAQEBAQEBAQAAAAAAAAAAAAAAAAAAAQEBAQEBAQEBAQEBAAAAAAAAAAAAAAAAAAAAAAAAAAABAQEBAQEBAQEBAQEAAAAAAAAAAAAAAAAAAAAAAAAAAAEBAQEBAQEBAQEBAQAAAAAAAAAAAAAAAAAAAQEBAQEBAQEBAQEBAQEBAQEBAAAAAAAAAAAAAAAAAAABAQEBAQEBAQEBAQEBAQEBAQEAAAAAAAAAAAAAAAAAAAEBAQEBAQEBAQEBAQEBAQEBAQAAAAAAAAAAAAAAAAAAAQEBAQEBAQEBAQEBAQEBAQEBAAAAAAAAAAAAAAAAAAABAQEBAQEBAQEBAQEBAQEBAQEAAAAAAAAAAAAAAAAAAAEBAQEBAQEBAQEBAQ==" - }, - "palette" : { - "originalArgb8888" : [ -265674 ], - "convertedRgb565" : [ -122 ] } }, "diagnostics" : [ ] @@ -258,14 +258,14 @@ "last_modified" : 1774359772421, "fingerprint" : "eeb7cc665386299403b7be1c272375d5077f3647c587f8033aa8c9275f840562", "metadata" : { + "palette" : { + "originalArgb8888" : [ -265674 ], + "convertedRgb565" : [ -122 ] + }, "tile" : { "width" : 32, "height" : 32, "paletteIndices" : "AQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAAAAAAAAAAABAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEAAAAAAAAAAAEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQAAAAAAAAAAAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAAAAAAAAAAABAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEAAAAAAAAAAAEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQAAAAAAAAAAAQEBAQEBAQEBAQEBAAAAAAAAAAAAAAAAAAAAAAAAAAABAQEBAQEBAQEBAQEAAAAAAAAAAAAAAAAAAAAAAAAAAAEBAQEBAQEBAQEBAQAAAAAAAAAAAAAAAAAAAAAAAAAAAQEBAQEBAQEBAQEBAAAAAAAAAAAAAAAAAAAAAAAAAAABAQEBAQEBAQEBAQEAAAAAAAAAAAAAAAAAAAAAAAAAAAEBAQEBAQEBAQEBAQAAAAAAAAAAAAAAAAAAAAAAAAAAAQEBAQEBAQEBAQEBAAAAAAAAAAAAAAAAAAAAAAAAAAABAQEBAQEBAQEBAQEAAAAAAAAAAAAAAAAAAAAAAAAAAAEBAQEBAQEBAQEBAQAAAAAAAAAAAAAAAAAAAQEBAQEBAQEBAQEBAQEBAQEBAAAAAAAAAAAAAAAAAAABAQEBAQEBAQEBAQEBAQEBAQEAAAAAAAAAAAAAAAAAAAEBAQEBAQEBAQEBAQEBAQEBAQAAAAAAAAAAAAAAAAAAAQEBAQEBAQEBAQEBAAAAAAAAAAAAAAAAAAAAAAAAAAABAQEBAQEBAQEBAQEAAAAAAAAAAAAAAAAAAAAAAAAAAAEBAQEBAQEBAQEBAQAAAAAAAAAAAAAAAAAAAQEBAQEBAQEBAQEBAQEBAQEBAAAAAAAAAAAAAAAAAAABAQEBAQEBAQEBAQEBAQEBAQEAAAAAAAAAAAAAAAAAAAEBAQEBAQEBAQEBAQEBAQEBAQAAAAAAAAAAAAAAAAAAAQEBAQEBAQEBAQEBAQEBAQEBAAAAAAAAAAAAAAAAAAABAQEBAQEBAQEBAQEBAQEBAQEAAAAAAAAAAAAAAAAAAAEBAQEBAQEBAQEBAQ==" - }, - "palette" : { - "originalArgb8888" : [ -265674 ], - "convertedRgb565" : [ -122 ] } }, "diagnostics" : [ ] @@ -276,14 +276,14 @@ "last_modified" : 1774359772423, "fingerprint" : "eeb7cc665386299403b7be1c272375d5077f3647c587f8033aa8c9275f840562", "metadata" : { + "palette" : { + "originalArgb8888" : [ -265674 ], + "convertedRgb565" : [ -122 ] + }, "tile" : { "width" : 32, "height" : 32, "paletteIndices" : "AQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAAAAAAAAAAABAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEAAAAAAAAAAAEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQAAAAAAAAAAAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAAAAAAAAAAABAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEAAAAAAAAAAAEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQAAAAAAAAAAAQEBAQEBAQEBAQEBAAAAAAAAAAAAAAAAAAAAAAAAAAABAQEBAQEBAQEBAQEAAAAAAAAAAAAAAAAAAAAAAAAAAAEBAQEBAQEBAQEBAQAAAAAAAAAAAAAAAAAAAAAAAAAAAQEBAQEBAQEBAQEBAAAAAAAAAAAAAAAAAAAAAAAAAAABAQEBAQEBAQEBAQEAAAAAAAAAAAAAAAAAAAAAAAAAAAEBAQEBAQEBAQEBAQAAAAAAAAAAAAAAAAAAAAAAAAAAAQEBAQEBAQEBAQEBAAAAAAAAAAAAAAAAAAAAAAAAAAABAQEBAQEBAQEBAQEAAAAAAAAAAAAAAAAAAAAAAAAAAAEBAQEBAQEBAQEBAQAAAAAAAAAAAAAAAAAAAQEBAQEBAQEBAQEBAQEBAQEBAAAAAAAAAAAAAAAAAAABAQEBAQEBAQEBAQEBAQEBAQEAAAAAAAAAAAAAAAAAAAEBAQEBAQEBAQEBAQEBAQEBAQAAAAAAAAAAAAAAAAAAAQEBAQEBAQEBAQEBAAAAAAAAAAAAAAAAAAAAAAAAAAABAQEBAQEBAQEBAQEAAAAAAAAAAAAAAAAAAAAAAAAAAAEBAQEBAQEBAQEBAQAAAAAAAAAAAAAAAAAAAQEBAQEBAQEBAQEBAQEBAQEBAAAAAAAAAAAAAAAAAAABAQEBAQEBAQEBAQEBAQEBAQEAAAAAAAAAAAAAAAAAAAEBAQEBAQEBAQEBAQEBAQEBAQAAAAAAAAAAAAAAAAAAAQEBAQEBAQEBAQEBAQEBAQEBAAAAAAAAAAAAAAAAAAABAQEBAQEBAQEBAQEBAQEBAQEAAAAAAAAAAAAAAAAAAAEBAQEBAQEBAQEBAQ==" - }, - "palette" : { - "originalArgb8888" : [ -265674 ], - "convertedRgb565" : [ -122 ] } }, "diagnostics" : [ ] @@ -294,14 +294,14 @@ "last_modified" : 1774359772424, "fingerprint" : "eeb7cc665386299403b7be1c272375d5077f3647c587f8033aa8c9275f840562", "metadata" : { + "palette" : { + "originalArgb8888" : [ -265674 ], + "convertedRgb565" : [ -122 ] + }, "tile" : { "width" : 32, "height" : 32, "paletteIndices" : "AQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAAAAAAAAAAABAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEAAAAAAAAAAAEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQAAAAAAAAAAAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAAAAAAAAAAABAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEAAAAAAAAAAAEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQAAAAAAAAAAAQEBAQEBAQEBAQEBAAAAAAAAAAAAAAAAAAAAAAAAAAABAQEBAQEBAQEBAQEAAAAAAAAAAAAAAAAAAAAAAAAAAAEBAQEBAQEBAQEBAQAAAAAAAAAAAAAAAAAAAAAAAAAAAQEBAQEBAQEBAQEBAAAAAAAAAAAAAAAAAAAAAAAAAAABAQEBAQEBAQEBAQEAAAAAAAAAAAAAAAAAAAAAAAAAAAEBAQEBAQEBAQEBAQAAAAAAAAAAAAAAAAAAAAAAAAAAAQEBAQEBAQEBAQEBAAAAAAAAAAAAAAAAAAAAAAAAAAABAQEBAQEBAQEBAQEAAAAAAAAAAAAAAAAAAAAAAAAAAAEBAQEBAQEBAQEBAQAAAAAAAAAAAAAAAAAAAQEBAQEBAQEBAQEBAQEBAQEBAAAAAAAAAAAAAAAAAAABAQEBAQEBAQEBAQEBAQEBAQEAAAAAAAAAAAAAAAAAAAEBAQEBAQEBAQEBAQEBAQEBAQAAAAAAAAAAAAAAAAAAAQEBAQEBAQEBAQEBAAAAAAAAAAAAAAAAAAAAAAAAAAABAQEBAQEBAQEBAQEAAAAAAAAAAAAAAAAAAAAAAAAAAAEBAQEBAQEBAQEBAQAAAAAAAAAAAAAAAAAAAQEBAQEBAQEBAQEBAQEBAQEBAAAAAAAAAAAAAAAAAAABAQEBAQEBAQEBAQEBAQEBAQEAAAAAAAAAAAAAAAAAAAEBAQEBAQEBAQEBAQEBAQEBAQAAAAAAAAAAAAAAAAAAAQEBAQEBAQEBAQEBAQEBAQEBAAAAAAAAAAAAAAAAAAABAQEBAQEBAQEBAQEBAQEBAQEAAAAAAAAAAAAAAAAAAAEBAQEBAQEBAQEBAQ==" - }, - "palette" : { - "originalArgb8888" : [ -265674 ], - "convertedRgb565" : [ -122 ] } }, "diagnostics" : [ ] @@ -312,14 +312,14 @@ "last_modified" : 1774359772425, "fingerprint" : "eeb7cc665386299403b7be1c272375d5077f3647c587f8033aa8c9275f840562", "metadata" : { + "palette" : { + "originalArgb8888" : [ -265674 ], + "convertedRgb565" : [ -122 ] + }, "tile" : { "width" : 32, "height" : 32, "paletteIndices" : "AQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAAAAAAAAAAABAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEAAAAAAAAAAAEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQAAAAAAAAAAAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAAAAAAAAAAABAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEAAAAAAAAAAAEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQAAAAAAAAAAAQEBAQEBAQEBAQEBAAAAAAAAAAAAAAAAAAAAAAAAAAABAQEBAQEBAQEBAQEAAAAAAAAAAAAAAAAAAAAAAAAAAAEBAQEBAQEBAQEBAQAAAAAAAAAAAAAAAAAAAAAAAAAAAQEBAQEBAQEBAQEBAAAAAAAAAAAAAAAAAAAAAAAAAAABAQEBAQEBAQEBAQEAAAAAAAAAAAAAAAAAAAAAAAAAAAEBAQEBAQEBAQEBAQAAAAAAAAAAAAAAAAAAAAAAAAAAAQEBAQEBAQEBAQEBAAAAAAAAAAAAAAAAAAAAAAAAAAABAQEBAQEBAQEBAQEAAAAAAAAAAAAAAAAAAAAAAAAAAAEBAQEBAQEBAQEBAQAAAAAAAAAAAAAAAAAAAQEBAQEBAQEBAQEBAQEBAQEBAAAAAAAAAAAAAAAAAAABAQEBAQEBAQEBAQEBAQEBAQEAAAAAAAAAAAAAAAAAAAEBAQEBAQEBAQEBAQEBAQEBAQAAAAAAAAAAAAAAAAAAAQEBAQEBAQEBAQEBAAAAAAAAAAAAAAAAAAAAAAAAAAABAQEBAQEBAQEBAQEAAAAAAAAAAAAAAAAAAAAAAAAAAAEBAQEBAQEBAQEBAQAAAAAAAAAAAAAAAAAAAQEBAQEBAQEBAQEBAQEBAQEBAAAAAAAAAAAAAAAAAAABAQEBAQEBAQEBAQEBAQEBAQEAAAAAAAAAAAAAAAAAAAEBAQEBAQEBAQEBAQEBAQEBAQAAAAAAAAAAAAAAAAAAAQEBAQEBAQEBAQEBAQEBAQEBAAAAAAAAAAAAAAAAAAABAQEBAQEBAQEBAQEBAQEBAQEAAAAAAAAAAAAAAAAAAAEBAQEBAQEBAQEBAQ==" - }, - "palette" : { - "originalArgb8888" : [ -265674 ], - "convertedRgb565" : [ -122 ] } }, "diagnostics" : [ ] @@ -330,14 +330,14 @@ "last_modified" : 1774359772426, "fingerprint" : "eeb7cc665386299403b7be1c272375d5077f3647c587f8033aa8c9275f840562", "metadata" : { + "palette" : { + "originalArgb8888" : [ -265674 ], + "convertedRgb565" : [ -122 ] + }, "tile" : { "width" : 32, "height" : 32, "paletteIndices" : "AQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAAAAAAAAAAABAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEAAAAAAAAAAAEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQAAAAAAAAAAAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAAAAAAAAAAABAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEAAAAAAAAAAAEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQAAAAAAAAAAAQEBAQEBAQEBAQEBAAAAAAAAAAAAAAAAAAAAAAAAAAABAQEBAQEBAQEBAQEAAAAAAAAAAAAAAAAAAAAAAAAAAAEBAQEBAQEBAQEBAQAAAAAAAAAAAAAAAAAAAAAAAAAAAQEBAQEBAQEBAQEBAAAAAAAAAAAAAAAAAAAAAAAAAAABAQEBAQEBAQEBAQEAAAAAAAAAAAAAAAAAAAAAAAAAAAEBAQEBAQEBAQEBAQAAAAAAAAAAAAAAAAAAAAAAAAAAAQEBAQEBAQEBAQEBAAAAAAAAAAAAAAAAAAAAAAAAAAABAQEBAQEBAQEBAQEAAAAAAAAAAAAAAAAAAAAAAAAAAAEBAQEBAQEBAQEBAQAAAAAAAAAAAAAAAAAAAQEBAQEBAQEBAQEBAQEBAQEBAAAAAAAAAAAAAAAAAAABAQEBAQEBAQEBAQEBAQEBAQEAAAAAAAAAAAAAAAAAAAEBAQEBAQEBAQEBAQEBAQEBAQAAAAAAAAAAAAAAAAAAAQEBAQEBAQEBAQEBAAAAAAAAAAAAAAAAAAAAAAAAAAABAQEBAQEBAQEBAQEAAAAAAAAAAAAAAAAAAAAAAAAAAAEBAQEBAQEBAQEBAQAAAAAAAAAAAAAAAAAAAQEBAQEBAQEBAQEBAQEBAQEBAAAAAAAAAAAAAAAAAAABAQEBAQEBAQEBAQEBAQEBAQEAAAAAAAAAAAAAAAAAAAEBAQEBAQEBAQEBAQEBAQEBAQAAAAAAAAAAAAAAAAAAAQEBAQEBAQEBAQEBAQEBAQEBAAAAAAAAAAAAAAAAAAABAQEBAQEBAQEBAQEBAQEBAQEAAAAAAAAAAAAAAAAAAAEBAQEBAQEBAQEBAQ==" - }, - "palette" : { - "originalArgb8888" : [ -265674 ], - "convertedRgb565" : [ -122 ] } }, "diagnostics" : [ ] @@ -348,14 +348,14 @@ "last_modified" : 1774359772428, "fingerprint" : "eeb7cc665386299403b7be1c272375d5077f3647c587f8033aa8c9275f840562", "metadata" : { + "palette" : { + "originalArgb8888" : [ -265674 ], + "convertedRgb565" : [ -122 ] + }, "tile" : { "width" : 32, "height" : 32, "paletteIndices" : "AQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAAAAAAAAAAABAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEAAAAAAAAAAAEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQAAAAAAAAAAAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAAAAAAAAAAABAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEAAAAAAAAAAAEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQAAAAAAAAAAAQEBAQEBAQEBAQEBAAAAAAAAAAAAAAAAAAAAAAAAAAABAQEBAQEBAQEBAQEAAAAAAAAAAAAAAAAAAAAAAAAAAAEBAQEBAQEBAQEBAQAAAAAAAAAAAAAAAAAAAAAAAAAAAQEBAQEBAQEBAQEBAAAAAAAAAAAAAAAAAAAAAAAAAAABAQEBAQEBAQEBAQEAAAAAAAAAAAAAAAAAAAAAAAAAAAEBAQEBAQEBAQEBAQAAAAAAAAAAAAAAAAAAAAAAAAAAAQEBAQEBAQEBAQEBAAAAAAAAAAAAAAAAAAAAAAAAAAABAQEBAQEBAQEBAQEAAAAAAAAAAAAAAAAAAAAAAAAAAAEBAQEBAQEBAQEBAQAAAAAAAAAAAAAAAAAAAQEBAQEBAQEBAQEBAQEBAQEBAAAAAAAAAAAAAAAAAAABAQEBAQEBAQEBAQEBAQEBAQEAAAAAAAAAAAAAAAAAAAEBAQEBAQEBAQEBAQEBAQEBAQAAAAAAAAAAAAAAAAAAAQEBAQEBAQEBAQEBAAAAAAAAAAAAAAAAAAAAAAAAAAABAQEBAQEBAQEBAQEAAAAAAAAAAAAAAAAAAAAAAAAAAAEBAQEBAQEBAQEBAQAAAAAAAAAAAAAAAAAAAQEBAQEBAQEBAQEBAQEBAQEBAAAAAAAAAAAAAAAAAAABAQEBAQEBAQEBAQEBAQEBAQEAAAAAAAAAAAAAAAAAAAEBAQEBAQEBAQEBAQEBAQEBAQAAAAAAAAAAAAAAAAAAAQEBAQEBAQEBAQEBAQEBAQEBAAAAAAAAAAAAAAAAAAABAQEBAQEBAQEBAQEBAQEBAQEAAAAAAAAAAAAAAAAAAAEBAQEBAQEBAQEBAQ==" - }, - "palette" : { - "originalArgb8888" : [ -265674 ], - "convertedRgb565" : [ -122 ] } }, "diagnostics" : [ ] @@ -366,14 +366,14 @@ "last_modified" : 1774359772429, "fingerprint" : "eeb7cc665386299403b7be1c272375d5077f3647c587f8033aa8c9275f840562", "metadata" : { + "palette" : { + "originalArgb8888" : [ -265674 ], + "convertedRgb565" : [ -122 ] + }, "tile" : { "width" : 32, "height" : 32, "paletteIndices" : "AQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAAAAAAAAAAABAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEAAAAAAAAAAAEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQAAAAAAAAAAAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAAAAAAAAAAABAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEAAAAAAAAAAAEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQAAAAAAAAAAAQEBAQEBAQEBAQEBAAAAAAAAAAAAAAAAAAAAAAAAAAABAQEBAQEBAQEBAQEAAAAAAAAAAAAAAAAAAAAAAAAAAAEBAQEBAQEBAQEBAQAAAAAAAAAAAAAAAAAAAAAAAAAAAQEBAQEBAQEBAQEBAAAAAAAAAAAAAAAAAAAAAAAAAAABAQEBAQEBAQEBAQEAAAAAAAAAAAAAAAAAAAAAAAAAAAEBAQEBAQEBAQEBAQAAAAAAAAAAAAAAAAAAAAAAAAAAAQEBAQEBAQEBAQEBAAAAAAAAAAAAAAAAAAAAAAAAAAABAQEBAQEBAQEBAQEAAAAAAAAAAAAAAAAAAAAAAAAAAAEBAQEBAQEBAQEBAQAAAAAAAAAAAAAAAAAAAQEBAQEBAQEBAQEBAQEBAQEBAAAAAAAAAAAAAAAAAAABAQEBAQEBAQEBAQEBAQEBAQEAAAAAAAAAAAAAAAAAAAEBAQEBAQEBAQEBAQEBAQEBAQAAAAAAAAAAAAAAAAAAAQEBAQEBAQEBAQEBAAAAAAAAAAAAAAAAAAAAAAAAAAABAQEBAQEBAQEBAQEAAAAAAAAAAAAAAAAAAAAAAAAAAAEBAQEBAQEBAQEBAQAAAAAAAAAAAAAAAAAAAQEBAQEBAQEBAQEBAQEBAQEBAAAAAAAAAAAAAAAAAAABAQEBAQEBAQEBAQEBAQEBAQEAAAAAAAAAAAAAAAAAAAEBAQEBAQEBAQEBAQEBAQEBAQAAAAAAAAAAAAAAAAAAAQEBAQEBAQEBAQEBAQEBAQEBAAAAAAAAAAAAAAAAAAABAQEBAQEBAQEBAQEBAQEBAQEAAAAAAAAAAAAAAAAAAAEBAQEBAQEBAQEBAQ==" - }, - "palette" : { - "originalArgb8888" : [ -265674 ], - "convertedRgb565" : [ -122 ] } }, "diagnostics" : [ ] @@ -384,14 +384,14 @@ "last_modified" : 1774359772430, "fingerprint" : "eeb7cc665386299403b7be1c272375d5077f3647c587f8033aa8c9275f840562", "metadata" : { + "palette" : { + "originalArgb8888" : [ -265674 ], + "convertedRgb565" : [ -122 ] + }, "tile" : { "width" : 32, "height" : 32, "paletteIndices" : "AQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAAAAAAAAAAABAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEAAAAAAAAAAAEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQAAAAAAAAAAAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAAAAAAAAAAABAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEAAAAAAAAAAAEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQAAAAAAAAAAAQEBAQEBAQEBAQEBAAAAAAAAAAAAAAAAAAAAAAAAAAABAQEBAQEBAQEBAQEAAAAAAAAAAAAAAAAAAAAAAAAAAAEBAQEBAQEBAQEBAQAAAAAAAAAAAAAAAAAAAAAAAAAAAQEBAQEBAQEBAQEBAAAAAAAAAAAAAAAAAAAAAAAAAAABAQEBAQEBAQEBAQEAAAAAAAAAAAAAAAAAAAAAAAAAAAEBAQEBAQEBAQEBAQAAAAAAAAAAAAAAAAAAAAAAAAAAAQEBAQEBAQEBAQEBAAAAAAAAAAAAAAAAAAAAAAAAAAABAQEBAQEBAQEBAQEAAAAAAAAAAAAAAAAAAAAAAAAAAAEBAQEBAQEBAQEBAQAAAAAAAAAAAAAAAAAAAQEBAQEBAQEBAQEBAQEBAQEBAAAAAAAAAAAAAAAAAAABAQEBAQEBAQEBAQEBAQEBAQEAAAAAAAAAAAAAAAAAAAEBAQEBAQEBAQEBAQEBAQEBAQAAAAAAAAAAAAAAAAAAAQEBAQEBAQEBAQEBAAAAAAAAAAAAAAAAAAAAAAAAAAABAQEBAQEBAQEBAQEAAAAAAAAAAAAAAAAAAAAAAAAAAAEBAQEBAQEBAQEBAQAAAAAAAAAAAAAAAAAAAQEBAQEBAQEBAQEBAQEBAQEBAAAAAAAAAAAAAAAAAAABAQEBAQEBAQEBAQEBAQEBAQEAAAAAAAAAAAAAAAAAAAEBAQEBAQEBAQEBAQEBAQEBAQAAAAAAAAAAAAAAAAAAAQEBAQEBAQEBAQEBAQEBAQEBAAAAAAAAAAAAAAAAAAABAQEBAQEBAQEBAQEBAQEBAQEAAAAAAAAAAAAAAAAAAAEBAQEBAQEBAQEBAQ==" - }, - "palette" : { - "originalArgb8888" : [ -265674 ], - "convertedRgb565" : [ -122 ] } }, "diagnostics" : [ ] @@ -402,14 +402,14 @@ "last_modified" : 1774359772431, "fingerprint" : "eeb7cc665386299403b7be1c272375d5077f3647c587f8033aa8c9275f840562", "metadata" : { + "palette" : { + "originalArgb8888" : [ -265674 ], + "convertedRgb565" : [ -122 ] + }, "tile" : { "width" : 32, "height" : 32, "paletteIndices" : "AQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAAAAAAAAAAABAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEAAAAAAAAAAAEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQAAAAAAAAAAAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAAAAAAAAAAABAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEAAAAAAAAAAAEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQAAAAAAAAAAAQEBAQEBAQEBAQEBAAAAAAAAAAAAAAAAAAAAAAAAAAABAQEBAQEBAQEBAQEAAAAAAAAAAAAAAAAAAAAAAAAAAAEBAQEBAQEBAQEBAQAAAAAAAAAAAAAAAAAAAAAAAAAAAQEBAQEBAQEBAQEBAAAAAAAAAAAAAAAAAAAAAAAAAAABAQEBAQEBAQEBAQEAAAAAAAAAAAAAAAAAAAAAAAAAAAEBAQEBAQEBAQEBAQAAAAAAAAAAAAAAAAAAAAAAAAAAAQEBAQEBAQEBAQEBAAAAAAAAAAAAAAAAAAAAAAAAAAABAQEBAQEBAQEBAQEAAAAAAAAAAAAAAAAAAAAAAAAAAAEBAQEBAQEBAQEBAQAAAAAAAAAAAAAAAAAAAQEBAQEBAQEBAQEBAQEBAQEBAAAAAAAAAAAAAAAAAAABAQEBAQEBAQEBAQEBAQEBAQEAAAAAAAAAAAAAAAAAAAEBAQEBAQEBAQEBAQEBAQEBAQAAAAAAAAAAAAAAAAAAAQEBAQEBAQEBAQEBAAAAAAAAAAAAAAAAAAAAAAAAAAABAQEBAQEBAQEBAQEAAAAAAAAAAAAAAAAAAAAAAAAAAAEBAQEBAQEBAQEBAQAAAAAAAAAAAAAAAAAAAQEBAQEBAQEBAQEBAQEBAQEBAAAAAAAAAAAAAAAAAAABAQEBAQEBAQEBAQEBAQEBAQEAAAAAAAAAAAAAAAAAAAEBAQEBAQEBAQEBAQEBAQEBAQAAAAAAAAAAAAAAAAAAAQEBAQEBAQEBAQEBAQEBAQEBAAAAAAAAAAAAAAAAAAABAQEBAQEBAQEBAQEBAQEBAQEAAAAAAAAAAAAAAAAAAAEBAQEBAQEBAQEBAQ==" - }, - "palette" : { - "originalArgb8888" : [ -265674 ], - "convertedRgb565" : [ -122 ] } }, "diagnostics" : [ ] @@ -420,14 +420,14 @@ "last_modified" : 1774359772432, "fingerprint" : "eeb7cc665386299403b7be1c272375d5077f3647c587f8033aa8c9275f840562", "metadata" : { + "palette" : { + "originalArgb8888" : [ -265674 ], + "convertedRgb565" : [ -122 ] + }, "tile" : { "width" : 32, "height" : 32, "paletteIndices" : "AQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAAAAAAAAAAABAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEAAAAAAAAAAAEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQAAAAAAAAAAAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAAAAAAAAAAABAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEAAAAAAAAAAAEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQAAAAAAAAAAAQEBAQEBAQEBAQEBAAAAAAAAAAAAAAAAAAAAAAAAAAABAQEBAQEBAQEBAQEAAAAAAAAAAAAAAAAAAAAAAAAAAAEBAQEBAQEBAQEBAQAAAAAAAAAAAAAAAAAAAAAAAAAAAQEBAQEBAQEBAQEBAAAAAAAAAAAAAAAAAAAAAAAAAAABAQEBAQEBAQEBAQEAAAAAAAAAAAAAAAAAAAAAAAAAAAEBAQEBAQEBAQEBAQAAAAAAAAAAAAAAAAAAAAAAAAAAAQEBAQEBAQEBAQEBAAAAAAAAAAAAAAAAAAAAAAAAAAABAQEBAQEBAQEBAQEAAAAAAAAAAAAAAAAAAAAAAAAAAAEBAQEBAQEBAQEBAQAAAAAAAAAAAAAAAAAAAQEBAQEBAQEBAQEBAQEBAQEBAAAAAAAAAAAAAAAAAAABAQEBAQEBAQEBAQEBAQEBAQEAAAAAAAAAAAAAAAAAAAEBAQEBAQEBAQEBAQEBAQEBAQAAAAAAAAAAAAAAAAAAAQEBAQEBAQEBAQEBAAAAAAAAAAAAAAAAAAAAAAAAAAABAQEBAQEBAQEBAQEAAAAAAAAAAAAAAAAAAAAAAAAAAAEBAQEBAQEBAQEBAQAAAAAAAAAAAAAAAAAAAQEBAQEBAQEBAQEBAQEBAQEBAAAAAAAAAAAAAAAAAAABAQEBAQEBAQEBAQEBAQEBAQEAAAAAAAAAAAAAAAAAAAEBAQEBAQEBAQEBAQEBAQEBAQAAAAAAAAAAAAAAAAAAAQEBAQEBAQEBAQEBAQEBAQEBAAAAAAAAAAAAAAAAAAABAQEBAQEBAQEBAQEBAQEBAQEAAAAAAAAAAAAAAAAAAAEBAQEBAQEBAQEBAQ==" - }, - "palette" : { - "originalArgb8888" : [ -265674 ], - "convertedRgb565" : [ -122 ] } }, "diagnostics" : [ ] @@ -438,14 +438,14 @@ "last_modified" : 1774359772433, "fingerprint" : "eeb7cc665386299403b7be1c272375d5077f3647c587f8033aa8c9275f840562", "metadata" : { + "palette" : { + "originalArgb8888" : [ -265674 ], + "convertedRgb565" : [ -122 ] + }, "tile" : { "width" : 32, "height" : 32, "paletteIndices" : "AQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAAAAAAAAAAABAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEAAAAAAAAAAAEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQAAAAAAAAAAAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAAAAAAAAAAABAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEAAAAAAAAAAAEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQAAAAAAAAAAAQEBAQEBAQEBAQEBAAAAAAAAAAAAAAAAAAAAAAAAAAABAQEBAQEBAQEBAQEAAAAAAAAAAAAAAAAAAAAAAAAAAAEBAQEBAQEBAQEBAQAAAAAAAAAAAAAAAAAAAAAAAAAAAQEBAQEBAQEBAQEBAAAAAAAAAAAAAAAAAAAAAAAAAAABAQEBAQEBAQEBAQEAAAAAAAAAAAAAAAAAAAAAAAAAAAEBAQEBAQEBAQEBAQAAAAAAAAAAAAAAAAAAAAAAAAAAAQEBAQEBAQEBAQEBAAAAAAAAAAAAAAAAAAAAAAAAAAABAQEBAQEBAQEBAQEAAAAAAAAAAAAAAAAAAAAAAAAAAAEBAQEBAQEBAQEBAQAAAAAAAAAAAAAAAAAAAQEBAQEBAQEBAQEBAQEBAQEBAAAAAAAAAAAAAAAAAAABAQEBAQEBAQEBAQEBAQEBAQEAAAAAAAAAAAAAAAAAAAEBAQEBAQEBAQEBAQEBAQEBAQAAAAAAAAAAAAAAAAAAAQEBAQEBAQEBAQEBAAAAAAAAAAAAAAAAAAAAAAAAAAABAQEBAQEBAQEBAQEAAAAAAAAAAAAAAAAAAAAAAAAAAAEBAQEBAQEBAQEBAQAAAAAAAAAAAAAAAAAAAQEBAQEBAQEBAQEBAQEBAQEBAAAAAAAAAAAAAAAAAAABAQEBAQEBAQEBAQEBAQEBAQEAAAAAAAAAAAAAAAAAAAEBAQEBAQEBAQEBAQEBAQEBAQAAAAAAAAAAAAAAAAAAAQEBAQEBAQEBAQEBAQEBAQEBAAAAAAAAAAAAAAAAAAABAQEBAQEBAQEBAQEBAQEBAQEAAAAAAAAAAAAAAAAAAAEBAQEBAQEBAQEBAQ==" - }, - "palette" : { - "originalArgb8888" : [ -265674 ], - "convertedRgb565" : [ -122 ] } }, "diagnostics" : [ ] @@ -456,14 +456,14 @@ "last_modified" : 1774359772435, "fingerprint" : "eeb7cc665386299403b7be1c272375d5077f3647c587f8033aa8c9275f840562", "metadata" : { + "palette" : { + "originalArgb8888" : [ -265674 ], + "convertedRgb565" : [ -122 ] + }, "tile" : { "width" : 32, "height" : 32, "paletteIndices" : "AQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAAAAAAAAAAABAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEAAAAAAAAAAAEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQAAAAAAAAAAAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAAAAAAAAAAABAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEAAAAAAAAAAAEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQAAAAAAAAAAAQEBAQEBAQEBAQEBAAAAAAAAAAAAAAAAAAAAAAAAAAABAQEBAQEBAQEBAQEAAAAAAAAAAAAAAAAAAAAAAAAAAAEBAQEBAQEBAQEBAQAAAAAAAAAAAAAAAAAAAAAAAAAAAQEBAQEBAQEBAQEBAAAAAAAAAAAAAAAAAAAAAAAAAAABAQEBAQEBAQEBAQEAAAAAAAAAAAAAAAAAAAAAAAAAAAEBAQEBAQEBAQEBAQAAAAAAAAAAAAAAAAAAAAAAAAAAAQEBAQEBAQEBAQEBAAAAAAAAAAAAAAAAAAAAAAAAAAABAQEBAQEBAQEBAQEAAAAAAAAAAAAAAAAAAAAAAAAAAAEBAQEBAQEBAQEBAQAAAAAAAAAAAAAAAAAAAQEBAQEBAQEBAQEBAQEBAQEBAAAAAAAAAAAAAAAAAAABAQEBAQEBAQEBAQEBAQEBAQEAAAAAAAAAAAAAAAAAAAEBAQEBAQEBAQEBAQEBAQEBAQAAAAAAAAAAAAAAAAAAAQEBAQEBAQEBAQEBAAAAAAAAAAAAAAAAAAAAAAAAAAABAQEBAQEBAQEBAQEAAAAAAAAAAAAAAAAAAAAAAAAAAAEBAQEBAQEBAQEBAQAAAAAAAAAAAAAAAAAAAQEBAQEBAQEBAQEBAQEBAQEBAAAAAAAAAAAAAAAAAAABAQEBAQEBAQEBAQEBAQEBAQEAAAAAAAAAAAAAAAAAAAEBAQEBAQEBAQEBAQEBAQEBAQAAAAAAAAAAAAAAAAAAAQEBAQEBAQEBAQEBAQEBAQEBAAAAAAAAAAAAAAAAAAABAQEBAQEBAQEBAQEBAQEBAQEAAAAAAAAAAAAAAAAAAAEBAQEBAQEBAQEBAQ==" - }, - "palette" : { - "originalArgb8888" : [ -265674 ], - "convertedRgb565" : [ -122 ] } }, "diagnostics" : [ ] @@ -474,14 +474,14 @@ "last_modified" : 1774359772436, "fingerprint" : "eeb7cc665386299403b7be1c272375d5077f3647c587f8033aa8c9275f840562", "metadata" : { + "palette" : { + "originalArgb8888" : [ -265674 ], + "convertedRgb565" : [ -122 ] + }, "tile" : { "width" : 32, "height" : 32, "paletteIndices" : "AQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAAAAAAAAAAABAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEAAAAAAAAAAAEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQAAAAAAAAAAAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAAAAAAAAAAABAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEAAAAAAAAAAAEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQAAAAAAAAAAAQEBAQEBAQEBAQEBAAAAAAAAAAAAAAAAAAAAAAAAAAABAQEBAQEBAQEBAQEAAAAAAAAAAAAAAAAAAAAAAAAAAAEBAQEBAQEBAQEBAQAAAAAAAAAAAAAAAAAAAAAAAAAAAQEBAQEBAQEBAQEBAAAAAAAAAAAAAAAAAAAAAAAAAAABAQEBAQEBAQEBAQEAAAAAAAAAAAAAAAAAAAAAAAAAAAEBAQEBAQEBAQEBAQAAAAAAAAAAAAAAAAAAAAAAAAAAAQEBAQEBAQEBAQEBAAAAAAAAAAAAAAAAAAAAAAAAAAABAQEBAQEBAQEBAQEAAAAAAAAAAAAAAAAAAAAAAAAAAAEBAQEBAQEBAQEBAQAAAAAAAAAAAAAAAAAAAQEBAQEBAQEBAQEBAQEBAQEBAAAAAAAAAAAAAAAAAAABAQEBAQEBAQEBAQEBAQEBAQEAAAAAAAAAAAAAAAAAAAEBAQEBAQEBAQEBAQEBAQEBAQAAAAAAAAAAAAAAAAAAAQEBAQEBAQEBAQEBAAAAAAAAAAAAAAAAAAAAAAAAAAABAQEBAQEBAQEBAQEAAAAAAAAAAAAAAAAAAAAAAAAAAAEBAQEBAQEBAQEBAQAAAAAAAAAAAAAAAAAAAQEBAQEBAQEBAQEBAQEBAQEBAAAAAAAAAAAAAAAAAAABAQEBAQEBAQEBAQEBAQEBAQEAAAAAAAAAAAAAAAAAAAEBAQEBAQEBAQEBAQEBAQEBAQAAAAAAAAAAAAAAAAAAAQEBAQEBAQEBAQEBAQEBAQEBAAAAAAAAAAAAAAAAAAABAQEBAQEBAQEBAQEBAQEBAQEAAAAAAAAAAAAAAAAAAAEBAQEBAQEBAQEBAQ==" - }, - "palette" : { - "originalArgb8888" : [ -265674 ], - "convertedRgb565" : [ -122 ] } }, "diagnostics" : [ ] @@ -492,14 +492,14 @@ "last_modified" : 1774359772437, "fingerprint" : "eeb7cc665386299403b7be1c272375d5077f3647c587f8033aa8c9275f840562", "metadata" : { + "palette" : { + "originalArgb8888" : [ -265674 ], + "convertedRgb565" : [ -122 ] + }, "tile" : { "width" : 32, "height" : 32, "paletteIndices" : "AQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAAAAAAAAAAABAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEAAAAAAAAAAAEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQAAAAAAAAAAAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAAAAAAAAAAABAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEAAAAAAAAAAAEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQAAAAAAAAAAAQEBAQEBAQEBAQEBAAAAAAAAAAAAAAAAAAAAAAAAAAABAQEBAQEBAQEBAQEAAAAAAAAAAAAAAAAAAAAAAAAAAAEBAQEBAQEBAQEBAQAAAAAAAAAAAAAAAAAAAAAAAAAAAQEBAQEBAQEBAQEBAAAAAAAAAAAAAAAAAAAAAAAAAAABAQEBAQEBAQEBAQEAAAAAAAAAAAAAAAAAAAAAAAAAAAEBAQEBAQEBAQEBAQAAAAAAAAAAAAAAAAAAAAAAAAAAAQEBAQEBAQEBAQEBAAAAAAAAAAAAAAAAAAAAAAAAAAABAQEBAQEBAQEBAQEAAAAAAAAAAAAAAAAAAAAAAAAAAAEBAQEBAQEBAQEBAQAAAAAAAAAAAAAAAAAAAQEBAQEBAQEBAQEBAQEBAQEBAAAAAAAAAAAAAAAAAAABAQEBAQEBAQEBAQEBAQEBAQEAAAAAAAAAAAAAAAAAAAEBAQEBAQEBAQEBAQEBAQEBAQAAAAAAAAAAAAAAAAAAAQEBAQEBAQEBAQEBAAAAAAAAAAAAAAAAAAAAAAAAAAABAQEBAQEBAQEBAQEAAAAAAAAAAAAAAAAAAAAAAAAAAAEBAQEBAQEBAQEBAQAAAAAAAAAAAAAAAAAAAQEBAQEBAQEBAQEBAQEBAQEBAAAAAAAAAAAAAAAAAAABAQEBAQEBAQEBAQEBAQEBAQEAAAAAAAAAAAAAAAAAAAEBAQEBAQEBAQEBAQEBAQEBAQAAAAAAAAAAAAAAAAAAAQEBAQEBAQEBAQEBAQEBAQEBAAAAAAAAAAAAAAAAAAABAQEBAQEBAQEBAQEBAQEBAQEAAAAAAAAAAAAAAAAAAAEBAQEBAQEBAQEBAQ==" - }, - "palette" : { - "originalArgb8888" : [ -265674 ], - "convertedRgb565" : [ -122 ] } }, "diagnostics" : [ ] @@ -510,14 +510,14 @@ "last_modified" : 1774359772438, "fingerprint" : "eeb7cc665386299403b7be1c272375d5077f3647c587f8033aa8c9275f840562", "metadata" : { + "palette" : { + "originalArgb8888" : [ -265674 ], + "convertedRgb565" : [ -122 ] + }, "tile" : { "width" : 32, "height" : 32, "paletteIndices" : "AQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAAAAAAAAAAABAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEAAAAAAAAAAAEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQAAAAAAAAAAAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAAAAAAAAAAABAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEAAAAAAAAAAAEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQAAAAAAAAAAAQEBAQEBAQEBAQEBAAAAAAAAAAAAAAAAAAAAAAAAAAABAQEBAQEBAQEBAQEAAAAAAAAAAAAAAAAAAAAAAAAAAAEBAQEBAQEBAQEBAQAAAAAAAAAAAAAAAAAAAAAAAAAAAQEBAQEBAQEBAQEBAAAAAAAAAAAAAAAAAAAAAAAAAAABAQEBAQEBAQEBAQEAAAAAAAAAAAAAAAAAAAAAAAAAAAEBAQEBAQEBAQEBAQAAAAAAAAAAAAAAAAAAAAAAAAAAAQEBAQEBAQEBAQEBAAAAAAAAAAAAAAAAAAAAAAAAAAABAQEBAQEBAQEBAQEAAAAAAAAAAAAAAAAAAAAAAAAAAAEBAQEBAQEBAQEBAQAAAAAAAAAAAAAAAAAAAQEBAQEBAQEBAQEBAQEBAQEBAAAAAAAAAAAAAAAAAAABAQEBAQEBAQEBAQEBAQEBAQEAAAAAAAAAAAAAAAAAAAEBAQEBAQEBAQEBAQEBAQEBAQAAAAAAAAAAAAAAAAAAAQEBAQEBAQEBAQEBAAAAAAAAAAAAAAAAAAAAAAAAAAABAQEBAQEBAQEBAQEAAAAAAAAAAAAAAAAAAAAAAAAAAAEBAQEBAQEBAQEBAQAAAAAAAAAAAAAAAAAAAQEBAQEBAQEBAQEBAQEBAQEBAAAAAAAAAAAAAAAAAAABAQEBAQEBAQEBAQEBAQEBAQEAAAAAAAAAAAAAAAAAAAEBAQEBAQEBAQEBAQEBAQEBAQAAAAAAAAAAAAAAAAAAAQEBAQEBAQEBAQEBAQEBAQEBAAAAAAAAAAAAAAAAAAABAQEBAQEBAQEBAQEBAQEBAQEAAAAAAAAAAAAAAAAAAAEBAQEBAQEBAQEBAQ==" - }, - "palette" : { - "originalArgb8888" : [ -265674 ], - "convertedRgb565" : [ -122 ] } }, "diagnostics" : [ ] @@ -528,14 +528,14 @@ "last_modified" : 1774359772439, "fingerprint" : "eeb7cc665386299403b7be1c272375d5077f3647c587f8033aa8c9275f840562", "metadata" : { + "palette" : { + "originalArgb8888" : [ -265674 ], + "convertedRgb565" : [ -122 ] + }, "tile" : { "width" : 32, "height" : 32, "paletteIndices" : "AQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAAAAAAAAAAABAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEAAAAAAAAAAAEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQAAAAAAAAAAAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAAAAAAAAAAABAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEAAAAAAAAAAAEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQAAAAAAAAAAAQEBAQEBAQEBAQEBAAAAAAAAAAAAAAAAAAAAAAAAAAABAQEBAQEBAQEBAQEAAAAAAAAAAAAAAAAAAAAAAAAAAAEBAQEBAQEBAQEBAQAAAAAAAAAAAAAAAAAAAAAAAAAAAQEBAQEBAQEBAQEBAAAAAAAAAAAAAAAAAAAAAAAAAAABAQEBAQEBAQEBAQEAAAAAAAAAAAAAAAAAAAAAAAAAAAEBAQEBAQEBAQEBAQAAAAAAAAAAAAAAAAAAAAAAAAAAAQEBAQEBAQEBAQEBAAAAAAAAAAAAAAAAAAAAAAAAAAABAQEBAQEBAQEBAQEAAAAAAAAAAAAAAAAAAAAAAAAAAAEBAQEBAQEBAQEBAQAAAAAAAAAAAAAAAAAAAQEBAQEBAQEBAQEBAQEBAQEBAAAAAAAAAAAAAAAAAAABAQEBAQEBAQEBAQEBAQEBAQEAAAAAAAAAAAAAAAAAAAEBAQEBAQEBAQEBAQEBAQEBAQAAAAAAAAAAAAAAAAAAAQEBAQEBAQEBAQEBAAAAAAAAAAAAAAAAAAAAAAAAAAABAQEBAQEBAQEBAQEAAAAAAAAAAAAAAAAAAAAAAAAAAAEBAQEBAQEBAQEBAQAAAAAAAAAAAAAAAAAAAQEBAQEBAQEBAQEBAQEBAQEBAAAAAAAAAAAAAAAAAAABAQEBAQEBAQEBAQEBAQEBAQEAAAAAAAAAAAAAAAAAAAEBAQEBAQEBAQEBAQEBAQEBAQAAAAAAAAAAAAAAAAAAAQEBAQEBAQEBAQEBAQEBAQEBAAAAAAAAAAAAAAAAAAABAQEBAQEBAQEBAQEBAQEBAQEAAAAAAAAAAAAAAAAAAAEBAQEBAQEBAQEBAQ==" - }, - "palette" : { - "originalArgb8888" : [ -265674 ], - "convertedRgb565" : [ -122 ] } }, "diagnostics" : [ ] @@ -546,14 +546,14 @@ "last_modified" : 1774359772441, "fingerprint" : "eeb7cc665386299403b7be1c272375d5077f3647c587f8033aa8c9275f840562", "metadata" : { + "palette" : { + "originalArgb8888" : [ -265674 ], + "convertedRgb565" : [ -122 ] + }, "tile" : { "width" : 32, "height" : 32, "paletteIndices" : "AQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAAAAAAAAAAABAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEAAAAAAAAAAAEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQAAAAAAAAAAAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAAAAAAAAAAABAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEAAAAAAAAAAAEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQAAAAAAAAAAAQEBAQEBAQEBAQEBAAAAAAAAAAAAAAAAAAAAAAAAAAABAQEBAQEBAQEBAQEAAAAAAAAAAAAAAAAAAAAAAAAAAAEBAQEBAQEBAQEBAQAAAAAAAAAAAAAAAAAAAAAAAAAAAQEBAQEBAQEBAQEBAAAAAAAAAAAAAAAAAAAAAAAAAAABAQEBAQEBAQEBAQEAAAAAAAAAAAAAAAAAAAAAAAAAAAEBAQEBAQEBAQEBAQAAAAAAAAAAAAAAAAAAAAAAAAAAAQEBAQEBAQEBAQEBAAAAAAAAAAAAAAAAAAAAAAAAAAABAQEBAQEBAQEBAQEAAAAAAAAAAAAAAAAAAAAAAAAAAAEBAQEBAQEBAQEBAQAAAAAAAAAAAAAAAAAAAQEBAQEBAQEBAQEBAQEBAQEBAAAAAAAAAAAAAAAAAAABAQEBAQEBAQEBAQEBAQEBAQEAAAAAAAAAAAAAAAAAAAEBAQEBAQEBAQEBAQEBAQEBAQAAAAAAAAAAAAAAAAAAAQEBAQEBAQEBAQEBAAAAAAAAAAAAAAAAAAAAAAAAAAABAQEBAQEBAQEBAQEAAAAAAAAAAAAAAAAAAAAAAAAAAAEBAQEBAQEBAQEBAQAAAAAAAAAAAAAAAAAAAQEBAQEBAQEBAQEBAQEBAQEBAAAAAAAAAAAAAAAAAAABAQEBAQEBAQEBAQEBAQEBAQEAAAAAAAAAAAAAAAAAAAEBAQEBAQEBAQEBAQEBAQEBAQAAAAAAAAAAAAAAAAAAAQEBAQEBAQEBAQEBAQEBAQEBAAAAAAAAAAAAAAAAAAABAQEBAQEBAQEBAQEBAQEBAQEAAAAAAAAAAAAAAAAAAAEBAQEBAQEBAQEBAQ==" - }, - "palette" : { - "originalArgb8888" : [ -265674 ], - "convertedRgb565" : [ -122 ] } }, "diagnostics" : [ ] @@ -564,14 +564,14 @@ "last_modified" : 1774359772442, "fingerprint" : "eeb7cc665386299403b7be1c272375d5077f3647c587f8033aa8c9275f840562", "metadata" : { + "palette" : { + "originalArgb8888" : [ -265674 ], + "convertedRgb565" : [ -122 ] + }, "tile" : { "width" : 32, "height" : 32, "paletteIndices" : "AQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAAAAAAAAAAABAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEAAAAAAAAAAAEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQAAAAAAAAAAAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAAAAAAAAAAABAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEAAAAAAAAAAAEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQAAAAAAAAAAAQEBAQEBAQEBAQEBAAAAAAAAAAAAAAAAAAAAAAAAAAABAQEBAQEBAQEBAQEAAAAAAAAAAAAAAAAAAAAAAAAAAAEBAQEBAQEBAQEBAQAAAAAAAAAAAAAAAAAAAAAAAAAAAQEBAQEBAQEBAQEBAAAAAAAAAAAAAAAAAAAAAAAAAAABAQEBAQEBAQEBAQEAAAAAAAAAAAAAAAAAAAAAAAAAAAEBAQEBAQEBAQEBAQAAAAAAAAAAAAAAAAAAAAAAAAAAAQEBAQEBAQEBAQEBAAAAAAAAAAAAAAAAAAAAAAAAAAABAQEBAQEBAQEBAQEAAAAAAAAAAAAAAAAAAAAAAAAAAAEBAQEBAQEBAQEBAQAAAAAAAAAAAAAAAAAAAQEBAQEBAQEBAQEBAQEBAQEBAAAAAAAAAAAAAAAAAAABAQEBAQEBAQEBAQEBAQEBAQEAAAAAAAAAAAAAAAAAAAEBAQEBAQEBAQEBAQEBAQEBAQAAAAAAAAAAAAAAAAAAAQEBAQEBAQEBAQEBAAAAAAAAAAAAAAAAAAAAAAAAAAABAQEBAQEBAQEBAQEAAAAAAAAAAAAAAAAAAAAAAAAAAAEBAQEBAQEBAQEBAQAAAAAAAAAAAAAAAAAAAQEBAQEBAQEBAQEBAQEBAQEBAAAAAAAAAAAAAAAAAAABAQEBAQEBAQEBAQEBAQEBAQEAAAAAAAAAAAAAAAAAAAEBAQEBAQEBAQEBAQEBAQEBAQAAAAAAAAAAAAAAAAAAAQEBAQEBAQEBAQEBAQEBAQEBAAAAAAAAAAAAAAAAAAABAQEBAQEBAQEBAQEBAQEBAQEAAAAAAAAAAAAAAAAAAAEBAQEBAQEBAQEBAQ==" - }, - "palette" : { - "originalArgb8888" : [ -265674 ], - "convertedRgb565" : [ -122 ] } }, "diagnostics" : [ ] @@ -582,14 +582,14 @@ "last_modified" : 1774359772443, "fingerprint" : "eeb7cc665386299403b7be1c272375d5077f3647c587f8033aa8c9275f840562", "metadata" : { + "palette" : { + "originalArgb8888" : [ -265674 ], + "convertedRgb565" : [ -122 ] + }, "tile" : { "width" : 32, "height" : 32, "paletteIndices" : "AQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAAAAAAAAAAABAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEAAAAAAAAAAAEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQAAAAAAAAAAAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAAAAAAAAAAABAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEAAAAAAAAAAAEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQAAAAAAAAAAAQEBAQEBAQEBAQEBAAAAAAAAAAAAAAAAAAAAAAAAAAABAQEBAQEBAQEBAQEAAAAAAAAAAAAAAAAAAAAAAAAAAAEBAQEBAQEBAQEBAQAAAAAAAAAAAAAAAAAAAAAAAAAAAQEBAQEBAQEBAQEBAAAAAAAAAAAAAAAAAAAAAAAAAAABAQEBAQEBAQEBAQEAAAAAAAAAAAAAAAAAAAAAAAAAAAEBAQEBAQEBAQEBAQAAAAAAAAAAAAAAAAAAAAAAAAAAAQEBAQEBAQEBAQEBAAAAAAAAAAAAAAAAAAAAAAAAAAABAQEBAQEBAQEBAQEAAAAAAAAAAAAAAAAAAAAAAAAAAAEBAQEBAQEBAQEBAQAAAAAAAAAAAAAAAAAAAQEBAQEBAQEBAQEBAQEBAQEBAAAAAAAAAAAAAAAAAAABAQEBAQEBAQEBAQEBAQEBAQEAAAAAAAAAAAAAAAAAAAEBAQEBAQEBAQEBAQEBAQEBAQAAAAAAAAAAAAAAAAAAAQEBAQEBAQEBAQEBAAAAAAAAAAAAAAAAAAAAAAAAAAABAQEBAQEBAQEBAQEAAAAAAAAAAAAAAAAAAAAAAAAAAAEBAQEBAQEBAQEBAQAAAAAAAAAAAAAAAAAAAQEBAQEBAQEBAQEBAQEBAQEBAAAAAAAAAAAAAAAAAAABAQEBAQEBAQEBAQEBAQEBAQEAAAAAAAAAAAAAAAAAAAEBAQEBAQEBAQEBAQEBAQEBAQAAAAAAAAAAAAAAAAAAAQEBAQEBAQEBAQEBAQEBAQEBAAAAAAAAAAAAAAAAAAABAQEBAQEBAQEBAQEBAQEBAQEAAAAAAAAAAAAAAAAAAAEBAQEBAQEBAQEBAQ==" - }, - "palette" : { - "originalArgb8888" : [ -265674 ], - "convertedRgb565" : [ -122 ] } }, "diagnostics" : [ ] @@ -600,14 +600,14 @@ "last_modified" : 1774359772444, "fingerprint" : "eeb7cc665386299403b7be1c272375d5077f3647c587f8033aa8c9275f840562", "metadata" : { + "palette" : { + "originalArgb8888" : [ -265674 ], + "convertedRgb565" : [ -122 ] + }, "tile" : { "width" : 32, "height" : 32, "paletteIndices" : "AQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAAAAAAAAAAABAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEAAAAAAAAAAAEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQAAAAAAAAAAAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAAAAAAAAAAABAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEAAAAAAAAAAAEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQAAAAAAAAAAAQEBAQEBAQEBAQEBAAAAAAAAAAAAAAAAAAAAAAAAAAABAQEBAQEBAQEBAQEAAAAAAAAAAAAAAAAAAAAAAAAAAAEBAQEBAQEBAQEBAQAAAAAAAAAAAAAAAAAAAAAAAAAAAQEBAQEBAQEBAQEBAAAAAAAAAAAAAAAAAAAAAAAAAAABAQEBAQEBAQEBAQEAAAAAAAAAAAAAAAAAAAAAAAAAAAEBAQEBAQEBAQEBAQAAAAAAAAAAAAAAAAAAAAAAAAAAAQEBAQEBAQEBAQEBAAAAAAAAAAAAAAAAAAAAAAAAAAABAQEBAQEBAQEBAQEAAAAAAAAAAAAAAAAAAAAAAAAAAAEBAQEBAQEBAQEBAQAAAAAAAAAAAAAAAAAAAQEBAQEBAQEBAQEBAQEBAQEBAAAAAAAAAAAAAAAAAAABAQEBAQEBAQEBAQEBAQEBAQEAAAAAAAAAAAAAAAAAAAEBAQEBAQEBAQEBAQEBAQEBAQAAAAAAAAAAAAAAAAAAAQEBAQEBAQEBAQEBAAAAAAAAAAAAAAAAAAAAAAAAAAABAQEBAQEBAQEBAQEAAAAAAAAAAAAAAAAAAAAAAAAAAAEBAQEBAQEBAQEBAQAAAAAAAAAAAAAAAAAAAQEBAQEBAQEBAQEBAQEBAQEBAAAAAAAAAAAAAAAAAAABAQEBAQEBAQEBAQEBAQEBAQEAAAAAAAAAAAAAAAAAAAEBAQEBAQEBAQEBAQEBAQEBAQAAAAAAAAAAAAAAAAAAAQEBAQEBAQEBAQEBAQEBAQEBAAAAAAAAAAAAAAAAAAABAQEBAQEBAQEBAQEBAQEBAQEAAAAAAAAAAAAAAAAAAAEBAQEBAQEBAQEBAQ==" - }, - "palette" : { - "originalArgb8888" : [ -265674 ], - "convertedRgb565" : [ -122 ] } }, "diagnostics" : [ ] @@ -618,14 +618,14 @@ "last_modified" : 1774359772445, "fingerprint" : "eeb7cc665386299403b7be1c272375d5077f3647c587f8033aa8c9275f840562", "metadata" : { + "palette" : { + "originalArgb8888" : [ -265674 ], + "convertedRgb565" : [ -122 ] + }, "tile" : { "width" : 32, "height" : 32, "paletteIndices" : "AQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAAAAAAAAAAABAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEAAAAAAAAAAAEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQAAAAAAAAAAAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAAAAAAAAAAABAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEAAAAAAAAAAAEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQAAAAAAAAAAAQEBAQEBAQEBAQEBAAAAAAAAAAAAAAAAAAAAAAAAAAABAQEBAQEBAQEBAQEAAAAAAAAAAAAAAAAAAAAAAAAAAAEBAQEBAQEBAQEBAQAAAAAAAAAAAAAAAAAAAAAAAAAAAQEBAQEBAQEBAQEBAAAAAAAAAAAAAAAAAAAAAAAAAAABAQEBAQEBAQEBAQEAAAAAAAAAAAAAAAAAAAAAAAAAAAEBAQEBAQEBAQEBAQAAAAAAAAAAAAAAAAAAAAAAAAAAAQEBAQEBAQEBAQEBAAAAAAAAAAAAAAAAAAAAAAAAAAABAQEBAQEBAQEBAQEAAAAAAAAAAAAAAAAAAAAAAAAAAAEBAQEBAQEBAQEBAQAAAAAAAAAAAAAAAAAAAQEBAQEBAQEBAQEBAQEBAQEBAAAAAAAAAAAAAAAAAAABAQEBAQEBAQEBAQEBAQEBAQEAAAAAAAAAAAAAAAAAAAEBAQEBAQEBAQEBAQEBAQEBAQAAAAAAAAAAAAAAAAAAAQEBAQEBAQEBAQEBAAAAAAAAAAAAAAAAAAAAAAAAAAABAQEBAQEBAQEBAQEAAAAAAAAAAAAAAAAAAAAAAAAAAAEBAQEBAQEBAQEBAQAAAAAAAAAAAAAAAAAAAQEBAQEBAQEBAQEBAQEBAQEBAAAAAAAAAAAAAAAAAAABAQEBAQEBAQEBAQEBAQEBAQEAAAAAAAAAAAAAAAAAAAEBAQEBAQEBAQEBAQEBAQEBAQAAAAAAAAAAAAAAAAAAAQEBAQEBAQEBAQEBAQEBAQEBAAAAAAAAAAAAAAAAAAABAQEBAQEBAQEBAQEBAQEBAQEAAAAAAAAAAAAAAAAAAAEBAQEBAQEBAQEBAQ==" - }, - "palette" : { - "originalArgb8888" : [ -265674 ], - "convertedRgb565" : [ -122 ] } }, "diagnostics" : [ ] @@ -636,14 +636,14 @@ "last_modified" : 1774359772448, "fingerprint" : "eeb7cc665386299403b7be1c272375d5077f3647c587f8033aa8c9275f840562", "metadata" : { + "palette" : { + "originalArgb8888" : [ -265674 ], + "convertedRgb565" : [ -122 ] + }, "tile" : { "width" : 32, "height" : 32, "paletteIndices" : "AQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAAAAAAAAAAABAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEAAAAAAAAAAAEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQAAAAAAAAAAAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAAAAAAAAAAABAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEAAAAAAAAAAAEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQAAAAAAAAAAAQEBAQEBAQEBAQEBAAAAAAAAAAAAAAAAAAAAAAAAAAABAQEBAQEBAQEBAQEAAAAAAAAAAAAAAAAAAAAAAAAAAAEBAQEBAQEBAQEBAQAAAAAAAAAAAAAAAAAAAAAAAAAAAQEBAQEBAQEBAQEBAAAAAAAAAAAAAAAAAAAAAAAAAAABAQEBAQEBAQEBAQEAAAAAAAAAAAAAAAAAAAAAAAAAAAEBAQEBAQEBAQEBAQAAAAAAAAAAAAAAAAAAAAAAAAAAAQEBAQEBAQEBAQEBAAAAAAAAAAAAAAAAAAAAAAAAAAABAQEBAQEBAQEBAQEAAAAAAAAAAAAAAAAAAAAAAAAAAAEBAQEBAQEBAQEBAQAAAAAAAAAAAAAAAAAAAQEBAQEBAQEBAQEBAQEBAQEBAAAAAAAAAAAAAAAAAAABAQEBAQEBAQEBAQEBAQEBAQEAAAAAAAAAAAAAAAAAAAEBAQEBAQEBAQEBAQEBAQEBAQAAAAAAAAAAAAAAAAAAAQEBAQEBAQEBAQEBAAAAAAAAAAAAAAAAAAAAAAAAAAABAQEBAQEBAQEBAQEAAAAAAAAAAAAAAAAAAAAAAAAAAAEBAQEBAQEBAQEBAQAAAAAAAAAAAAAAAAAAAQEBAQEBAQEBAQEBAQEBAQEBAAAAAAAAAAAAAAAAAAABAQEBAQEBAQEBAQEBAQEBAQEAAAAAAAAAAAAAAAAAAAEBAQEBAQEBAQEBAQEBAQEBAQAAAAAAAAAAAAAAAAAAAQEBAQEBAQEBAQEBAQEBAQEBAAAAAAAAAAAAAAAAAAABAQEBAQEBAQEBAQEBAQEBAQEAAAAAAAAAAAAAAAAAAAEBAQEBAQEBAQEBAQ==" - }, - "palette" : { - "originalArgb8888" : [ -265674 ], - "convertedRgb565" : [ -122 ] } }, "diagnostics" : [ ] @@ -654,14 +654,14 @@ "last_modified" : 1774359772449, "fingerprint" : "eeb7cc665386299403b7be1c272375d5077f3647c587f8033aa8c9275f840562", "metadata" : { + "palette" : { + "originalArgb8888" : [ -265674 ], + "convertedRgb565" : [ -122 ] + }, "tile" : { "width" : 32, "height" : 32, "paletteIndices" : "AQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAAAAAAAAAAABAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEAAAAAAAAAAAEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQAAAAAAAAAAAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAAAAAAAAAAABAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEAAAAAAAAAAAEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQAAAAAAAAAAAQEBAQEBAQEBAQEBAAAAAAAAAAAAAAAAAAAAAAAAAAABAQEBAQEBAQEBAQEAAAAAAAAAAAAAAAAAAAAAAAAAAAEBAQEBAQEBAQEBAQAAAAAAAAAAAAAAAAAAAAAAAAAAAQEBAQEBAQEBAQEBAAAAAAAAAAAAAAAAAAAAAAAAAAABAQEBAQEBAQEBAQEAAAAAAAAAAAAAAAAAAAAAAAAAAAEBAQEBAQEBAQEBAQAAAAAAAAAAAAAAAAAAAAAAAAAAAQEBAQEBAQEBAQEBAAAAAAAAAAAAAAAAAAAAAAAAAAABAQEBAQEBAQEBAQEAAAAAAAAAAAAAAAAAAAAAAAAAAAEBAQEBAQEBAQEBAQAAAAAAAAAAAAAAAAAAAQEBAQEBAQEBAQEBAQEBAQEBAAAAAAAAAAAAAAAAAAABAQEBAQEBAQEBAQEBAQEBAQEAAAAAAAAAAAAAAAAAAAEBAQEBAQEBAQEBAQEBAQEBAQAAAAAAAAAAAAAAAAAAAQEBAQEBAQEBAQEBAAAAAAAAAAAAAAAAAAAAAAAAAAABAQEBAQEBAQEBAQEAAAAAAAAAAAAAAAAAAAAAAAAAAAEBAQEBAQEBAQEBAQAAAAAAAAAAAAAAAAAAAQEBAQEBAQEBAQEBAQEBAQEBAAAAAAAAAAAAAAAAAAABAQEBAQEBAQEBAQEBAQEBAQEAAAAAAAAAAAAAAAAAAAEBAQEBAQEBAQEBAQEBAQEBAQAAAAAAAAAAAAAAAAAAAQEBAQEBAQEBAQEBAQEBAQEBAAAAAAAAAAAAAAAAAAABAQEBAQEBAQEBAQEBAQEBAQEAAAAAAAAAAAAAAAAAAAEBAQEBAQEBAQEBAQ==" - }, - "palette" : { - "originalArgb8888" : [ -265674 ], - "convertedRgb565" : [ -122 ] } }, "diagnostics" : [ ] @@ -672,14 +672,14 @@ "last_modified" : 1774359772450, "fingerprint" : "eeb7cc665386299403b7be1c272375d5077f3647c587f8033aa8c9275f840562", "metadata" : { + "palette" : { + "originalArgb8888" : [ -265674 ], + "convertedRgb565" : [ -122 ] + }, "tile" : { "width" : 32, "height" : 32, "paletteIndices" : "AQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAAAAAAAAAAABAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEAAAAAAAAAAAEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQAAAAAAAAAAAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAAAAAAAAAAABAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEAAAAAAAAAAAEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQAAAAAAAAAAAQEBAQEBAQEBAQEBAAAAAAAAAAAAAAAAAAAAAAAAAAABAQEBAQEBAQEBAQEAAAAAAAAAAAAAAAAAAAAAAAAAAAEBAQEBAQEBAQEBAQAAAAAAAAAAAAAAAAAAAAAAAAAAAQEBAQEBAQEBAQEBAAAAAAAAAAAAAAAAAAAAAAAAAAABAQEBAQEBAQEBAQEAAAAAAAAAAAAAAAAAAAAAAAAAAAEBAQEBAQEBAQEBAQAAAAAAAAAAAAAAAAAAAAAAAAAAAQEBAQEBAQEBAQEBAAAAAAAAAAAAAAAAAAAAAAAAAAABAQEBAQEBAQEBAQEAAAAAAAAAAAAAAAAAAAAAAAAAAAEBAQEBAQEBAQEBAQAAAAAAAAAAAAAAAAAAAQEBAQEBAQEBAQEBAQEBAQEBAAAAAAAAAAAAAAAAAAABAQEBAQEBAQEBAQEBAQEBAQEAAAAAAAAAAAAAAAAAAAEBAQEBAQEBAQEBAQEBAQEBAQAAAAAAAAAAAAAAAAAAAQEBAQEBAQEBAQEBAAAAAAAAAAAAAAAAAAAAAAAAAAABAQEBAQEBAQEBAQEAAAAAAAAAAAAAAAAAAAAAAAAAAAEBAQEBAQEBAQEBAQAAAAAAAAAAAAAAAAAAAQEBAQEBAQEBAQEBAQEBAQEBAAAAAAAAAAAAAAAAAAABAQEBAQEBAQEBAQEBAQEBAQEAAAAAAAAAAAAAAAAAAAEBAQEBAQEBAQEBAQEBAQEBAQAAAAAAAAAAAAAAAAAAAQEBAQEBAQEBAQEBAQEBAQEBAAAAAAAAAAAAAAAAAAABAQEBAQEBAQEBAQEBAQEBAQEAAAAAAAAAAAAAAAAAAAEBAQEBAQEBAQEBAQ==" - }, - "palette" : { - "originalArgb8888" : [ -265674 ], - "convertedRgb565" : [ -122 ] } }, "diagnostics" : [ ] @@ -690,14 +690,14 @@ "last_modified" : 1774359772452, "fingerprint" : "eeb7cc665386299403b7be1c272375d5077f3647c587f8033aa8c9275f840562", "metadata" : { + "palette" : { + "originalArgb8888" : [ -265674 ], + "convertedRgb565" : [ -122 ] + }, "tile" : { "width" : 32, "height" : 32, "paletteIndices" : "AQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAAAAAAAAAAABAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEAAAAAAAAAAAEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQAAAAAAAAAAAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAAAAAAAAAAABAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEAAAAAAAAAAAEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQAAAAAAAAAAAQEBAQEBAQEBAQEBAAAAAAAAAAAAAAAAAAAAAAAAAAABAQEBAQEBAQEBAQEAAAAAAAAAAAAAAAAAAAAAAAAAAAEBAQEBAQEBAQEBAQAAAAAAAAAAAAAAAAAAAAAAAAAAAQEBAQEBAQEBAQEBAAAAAAAAAAAAAAAAAAAAAAAAAAABAQEBAQEBAQEBAQEAAAAAAAAAAAAAAAAAAAAAAAAAAAEBAQEBAQEBAQEBAQAAAAAAAAAAAAAAAAAAAAAAAAAAAQEBAQEBAQEBAQEBAAAAAAAAAAAAAAAAAAAAAAAAAAABAQEBAQEBAQEBAQEAAAAAAAAAAAAAAAAAAAAAAAAAAAEBAQEBAQEBAQEBAQAAAAAAAAAAAAAAAAAAAQEBAQEBAQEBAQEBAQEBAQEBAAAAAAAAAAAAAAAAAAABAQEBAQEBAQEBAQEBAQEBAQEAAAAAAAAAAAAAAAAAAAEBAQEBAQEBAQEBAQEBAQEBAQAAAAAAAAAAAAAAAAAAAQEBAQEBAQEBAQEBAAAAAAAAAAAAAAAAAAAAAAAAAAABAQEBAQEBAQEBAQEAAAAAAAAAAAAAAAAAAAAAAAAAAAEBAQEBAQEBAQEBAQAAAAAAAAAAAAAAAAAAAQEBAQEBAQEBAQEBAQEBAQEBAAAAAAAAAAAAAAAAAAABAQEBAQEBAQEBAQEBAQEBAQEAAAAAAAAAAAAAAAAAAAEBAQEBAQEBAQEBAQEBAQEBAQAAAAAAAAAAAAAAAAAAAQEBAQEBAQEBAQEBAQEBAQEBAAAAAAAAAAAAAAAAAAABAQEBAQEBAQEBAQEBAQEBAQEAAAAAAAAAAAAAAAAAAAEBAQEBAQEBAQEBAQ==" - }, - "palette" : { - "originalArgb8888" : [ -265674 ], - "convertedRgb565" : [ -122 ] } }, "diagnostics" : [ ] @@ -708,14 +708,14 @@ "last_modified" : 1774359772453, "fingerprint" : "eeb7cc665386299403b7be1c272375d5077f3647c587f8033aa8c9275f840562", "metadata" : { + "palette" : { + "originalArgb8888" : [ -265674 ], + "convertedRgb565" : [ -122 ] + }, "tile" : { "width" : 32, "height" : 32, "paletteIndices" : "AQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAAAAAAAAAAABAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEAAAAAAAAAAAEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQAAAAAAAAAAAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAAAAAAAAAAABAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEAAAAAAAAAAAEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQAAAAAAAAAAAQEBAQEBAQEBAQEBAAAAAAAAAAAAAAAAAAAAAAAAAAABAQEBAQEBAQEBAQEAAAAAAAAAAAAAAAAAAAAAAAAAAAEBAQEBAQEBAQEBAQAAAAAAAAAAAAAAAAAAAAAAAAAAAQEBAQEBAQEBAQEBAAAAAAAAAAAAAAAAAAAAAAAAAAABAQEBAQEBAQEBAQEAAAAAAAAAAAAAAAAAAAAAAAAAAAEBAQEBAQEBAQEBAQAAAAAAAAAAAAAAAAAAAAAAAAAAAQEBAQEBAQEBAQEBAAAAAAAAAAAAAAAAAAAAAAAAAAABAQEBAQEBAQEBAQEAAAAAAAAAAAAAAAAAAAAAAAAAAAEBAQEBAQEBAQEBAQAAAAAAAAAAAAAAAAAAAQEBAQEBAQEBAQEBAQEBAQEBAAAAAAAAAAAAAAAAAAABAQEBAQEBAQEBAQEBAQEBAQEAAAAAAAAAAAAAAAAAAAEBAQEBAQEBAQEBAQEBAQEBAQAAAAAAAAAAAAAAAAAAAQEBAQEBAQEBAQEBAAAAAAAAAAAAAAAAAAAAAAAAAAABAQEBAQEBAQEBAQEAAAAAAAAAAAAAAAAAAAAAAAAAAAEBAQEBAQEBAQEBAQAAAAAAAAAAAAAAAAAAAQEBAQEBAQEBAQEBAQEBAQEBAAAAAAAAAAAAAAAAAAABAQEBAQEBAQEBAQEBAQEBAQEAAAAAAAAAAAAAAAAAAAEBAQEBAQEBAQEBAQEBAQEBAQAAAAAAAAAAAAAAAAAAAQEBAQEBAQEBAQEBAQEBAQEBAAAAAAAAAAAAAAAAAAABAQEBAQEBAQEBAQEBAQEBAQEAAAAAAAAAAAAAAAAAAAEBAQEBAQEBAQEBAQ==" - }, - "palette" : { - "originalArgb8888" : [ -265674 ], - "convertedRgb565" : [ -122 ] } }, "diagnostics" : [ ] @@ -726,14 +726,14 @@ "last_modified" : 1774359772454, "fingerprint" : "eeb7cc665386299403b7be1c272375d5077f3647c587f8033aa8c9275f840562", "metadata" : { + "palette" : { + "originalArgb8888" : [ -265674 ], + "convertedRgb565" : [ -122 ] + }, "tile" : { "width" : 32, "height" : 32, "paletteIndices" : "AQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAAAAAAAAAAABAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEAAAAAAAAAAAEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQAAAAAAAAAAAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAAAAAAAAAAABAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEAAAAAAAAAAAEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQAAAAAAAAAAAQEBAQEBAQEBAQEBAAAAAAAAAAAAAAAAAAAAAAAAAAABAQEBAQEBAQEBAQEAAAAAAAAAAAAAAAAAAAAAAAAAAAEBAQEBAQEBAQEBAQAAAAAAAAAAAAAAAAAAAAAAAAAAAQEBAQEBAQEBAQEBAAAAAAAAAAAAAAAAAAAAAAAAAAABAQEBAQEBAQEBAQEAAAAAAAAAAAAAAAAAAAAAAAAAAAEBAQEBAQEBAQEBAQAAAAAAAAAAAAAAAAAAAAAAAAAAAQEBAQEBAQEBAQEBAAAAAAAAAAAAAAAAAAAAAAAAAAABAQEBAQEBAQEBAQEAAAAAAAAAAAAAAAAAAAAAAAAAAAEBAQEBAQEBAQEBAQAAAAAAAAAAAAAAAAAAAQEBAQEBAQEBAQEBAQEBAQEBAAAAAAAAAAAAAAAAAAABAQEBAQEBAQEBAQEBAQEBAQEAAAAAAAAAAAAAAAAAAAEBAQEBAQEBAQEBAQEBAQEBAQAAAAAAAAAAAAAAAAAAAQEBAQEBAQEBAQEBAAAAAAAAAAAAAAAAAAAAAAAAAAABAQEBAQEBAQEBAQEAAAAAAAAAAAAAAAAAAAAAAAAAAAEBAQEBAQEBAQEBAQAAAAAAAAAAAAAAAAAAAQEBAQEBAQEBAQEBAQEBAQEBAAAAAAAAAAAAAAAAAAABAQEBAQEBAQEBAQEBAQEBAQEAAAAAAAAAAAAAAAAAAAEBAQEBAQEBAQEBAQEBAQEBAQAAAAAAAAAAAAAAAAAAAQEBAQEBAQEBAQEBAQEBAQEBAAAAAAAAAAAAAAAAAAABAQEBAQEBAQEBAQEBAQEBAQEAAAAAAAAAAAAAAAAAAAEBAQEBAQEBAQEBAQ==" - }, - "palette" : { - "originalArgb8888" : [ -265674 ], - "convertedRgb565" : [ -122 ] } }, "diagnostics" : [ ] @@ -744,14 +744,14 @@ "last_modified" : 1774359772455, "fingerprint" : "eeb7cc665386299403b7be1c272375d5077f3647c587f8033aa8c9275f840562", "metadata" : { + "palette" : { + "originalArgb8888" : [ -265674 ], + "convertedRgb565" : [ -122 ] + }, "tile" : { "width" : 32, "height" : 32, "paletteIndices" : "AQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAAAAAAAAAAABAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEAAAAAAAAAAAEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQAAAAAAAAAAAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAAAAAAAAAAABAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEAAAAAAAAAAAEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQAAAAAAAAAAAQEBAQEBAQEBAQEBAAAAAAAAAAAAAAAAAAAAAAAAAAABAQEBAQEBAQEBAQEAAAAAAAAAAAAAAAAAAAAAAAAAAAEBAQEBAQEBAQEBAQAAAAAAAAAAAAAAAAAAAAAAAAAAAQEBAQEBAQEBAQEBAAAAAAAAAAAAAAAAAAAAAAAAAAABAQEBAQEBAQEBAQEAAAAAAAAAAAAAAAAAAAAAAAAAAAEBAQEBAQEBAQEBAQAAAAAAAAAAAAAAAAAAAAAAAAAAAQEBAQEBAQEBAQEBAAAAAAAAAAAAAAAAAAAAAAAAAAABAQEBAQEBAQEBAQEAAAAAAAAAAAAAAAAAAAAAAAAAAAEBAQEBAQEBAQEBAQAAAAAAAAAAAAAAAAAAAQEBAQEBAQEBAQEBAQEBAQEBAAAAAAAAAAAAAAAAAAABAQEBAQEBAQEBAQEBAQEBAQEAAAAAAAAAAAAAAAAAAAEBAQEBAQEBAQEBAQEBAQEBAQAAAAAAAAAAAAAAAAAAAQEBAQEBAQEBAQEBAAAAAAAAAAAAAAAAAAAAAAAAAAABAQEBAQEBAQEBAQEAAAAAAAAAAAAAAAAAAAAAAAAAAAEBAQEBAQEBAQEBAQAAAAAAAAAAAAAAAAAAAQEBAQEBAQEBAQEBAQEBAQEBAAAAAAAAAAAAAAAAAAABAQEBAQEBAQEBAQEBAQEBAQEAAAAAAAAAAAAAAAAAAAEBAQEBAQEBAQEBAQEBAQEBAQAAAAAAAAAAAAAAAAAAAQEBAQEBAQEBAQEBAQEBAQEBAAAAAAAAAAAAAAAAAAABAQEBAQEBAQEBAQEBAQEBAQEAAAAAAAAAAAAAAAAAAAEBAQEBAQEBAQEBAQ==" - }, - "palette" : { - "originalArgb8888" : [ -265674 ], - "convertedRgb565" : [ -122 ] } }, "diagnostics" : [ ] @@ -762,14 +762,14 @@ "last_modified" : 1774359772456, "fingerprint" : "eeb7cc665386299403b7be1c272375d5077f3647c587f8033aa8c9275f840562", "metadata" : { + "palette" : { + "originalArgb8888" : [ -265674 ], + "convertedRgb565" : [ -122 ] + }, "tile" : { "width" : 32, "height" : 32, "paletteIndices" : "AQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAAAAAAAAAAABAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEAAAAAAAAAAAEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQAAAAAAAAAAAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAAAAAAAAAAABAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEAAAAAAAAAAAEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQAAAAAAAAAAAQEBAQEBAQEBAQEBAAAAAAAAAAAAAAAAAAAAAAAAAAABAQEBAQEBAQEBAQEAAAAAAAAAAAAAAAAAAAAAAAAAAAEBAQEBAQEBAQEBAQAAAAAAAAAAAAAAAAAAAAAAAAAAAQEBAQEBAQEBAQEBAAAAAAAAAAAAAAAAAAAAAAAAAAABAQEBAQEBAQEBAQEAAAAAAAAAAAAAAAAAAAAAAAAAAAEBAQEBAQEBAQEBAQAAAAAAAAAAAAAAAAAAAAAAAAAAAQEBAQEBAQEBAQEBAAAAAAAAAAAAAAAAAAAAAAAAAAABAQEBAQEBAQEBAQEAAAAAAAAAAAAAAAAAAAAAAAAAAAEBAQEBAQEBAQEBAQAAAAAAAAAAAAAAAAAAAQEBAQEBAQEBAQEBAQEBAQEBAAAAAAAAAAAAAAAAAAABAQEBAQEBAQEBAQEBAQEBAQEAAAAAAAAAAAAAAAAAAAEBAQEBAQEBAQEBAQEBAQEBAQAAAAAAAAAAAAAAAAAAAQEBAQEBAQEBAQEBAAAAAAAAAAAAAAAAAAAAAAAAAAABAQEBAQEBAQEBAQEAAAAAAAAAAAAAAAAAAAAAAAAAAAEBAQEBAQEBAQEBAQAAAAAAAAAAAAAAAAAAAQEBAQEBAQEBAQEBAQEBAQEBAAAAAAAAAAAAAAAAAAABAQEBAQEBAQEBAQEBAQEBAQEAAAAAAAAAAAAAAAAAAAEBAQEBAQEBAQEBAQEBAQEBAQAAAAAAAAAAAAAAAAAAAQEBAQEBAQEBAQEBAQEBAQEBAAAAAAAAAAAAAAAAAAABAQEBAQEBAQEBAQEBAQEBAQEAAAAAAAAAAAAAAAAAAAEBAQEBAQEBAQEBAQ==" - }, - "palette" : { - "originalArgb8888" : [ -265674 ], - "convertedRgb565" : [ -122 ] } }, "diagnostics" : [ ] @@ -780,14 +780,14 @@ "last_modified" : 1774359772458, "fingerprint" : "eeb7cc665386299403b7be1c272375d5077f3647c587f8033aa8c9275f840562", "metadata" : { + "palette" : { + "originalArgb8888" : [ -265674 ], + "convertedRgb565" : [ -122 ] + }, "tile" : { "width" : 32, "height" : 32, "paletteIndices" : "AQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAAAAAAAAAAABAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEAAAAAAAAAAAEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQAAAAAAAAAAAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAAAAAAAAAAABAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEAAAAAAAAAAAEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQAAAAAAAAAAAQEBAQEBAQEBAQEBAAAAAAAAAAAAAAAAAAAAAAAAAAABAQEBAQEBAQEBAQEAAAAAAAAAAAAAAAAAAAAAAAAAAAEBAQEBAQEBAQEBAQAAAAAAAAAAAAAAAAAAAAAAAAAAAQEBAQEBAQEBAQEBAAAAAAAAAAAAAAAAAAAAAAAAAAABAQEBAQEBAQEBAQEAAAAAAAAAAAAAAAAAAAAAAAAAAAEBAQEBAQEBAQEBAQAAAAAAAAAAAAAAAAAAAAAAAAAAAQEBAQEBAQEBAQEBAAAAAAAAAAAAAAAAAAAAAAAAAAABAQEBAQEBAQEBAQEAAAAAAAAAAAAAAAAAAAAAAAAAAAEBAQEBAQEBAQEBAQAAAAAAAAAAAAAAAAAAAQEBAQEBAQEBAQEBAQEBAQEBAAAAAAAAAAAAAAAAAAABAQEBAQEBAQEBAQEBAQEBAQEAAAAAAAAAAAAAAAAAAAEBAQEBAQEBAQEBAQEBAQEBAQAAAAAAAAAAAAAAAAAAAQEBAQEBAQEBAQEBAAAAAAAAAAAAAAAAAAAAAAAAAAABAQEBAQEBAQEBAQEAAAAAAAAAAAAAAAAAAAAAAAAAAAEBAQEBAQEBAQEBAQAAAAAAAAAAAAAAAAAAAQEBAQEBAQEBAQEBAQEBAQEBAAAAAAAAAAAAAAAAAAABAQEBAQEBAQEBAQEBAQEBAQEAAAAAAAAAAAAAAAAAAAEBAQEBAQEBAQEBAQEBAQEBAQAAAAAAAAAAAAAAAAAAAQEBAQEBAQEBAQEBAQEBAQEBAAAAAAAAAAAAAAAAAAABAQEBAQEBAQEBAQEBAQEBAQEAAAAAAAAAAAAAAAAAAAEBAQEBAQEBAQEBAQ==" - }, - "palette" : { - "originalArgb8888" : [ -265674 ], - "convertedRgb565" : [ -122 ] } }, "diagnostics" : [ ] @@ -798,14 +798,14 @@ "last_modified" : 1774359772459, "fingerprint" : "eeb7cc665386299403b7be1c272375d5077f3647c587f8033aa8c9275f840562", "metadata" : { + "palette" : { + "originalArgb8888" : [ -265674 ], + "convertedRgb565" : [ -122 ] + }, "tile" : { "width" : 32, "height" : 32, "paletteIndices" : "AQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAAAAAAAAAAABAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEAAAAAAAAAAAEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQAAAAAAAAAAAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAAAAAAAAAAABAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEAAAAAAAAAAAEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQAAAAAAAAAAAQEBAQEBAQEBAQEBAAAAAAAAAAAAAAAAAAAAAAAAAAABAQEBAQEBAQEBAQEAAAAAAAAAAAAAAAAAAAAAAAAAAAEBAQEBAQEBAQEBAQAAAAAAAAAAAAAAAAAAAAAAAAAAAQEBAQEBAQEBAQEBAAAAAAAAAAAAAAAAAAAAAAAAAAABAQEBAQEBAQEBAQEAAAAAAAAAAAAAAAAAAAAAAAAAAAEBAQEBAQEBAQEBAQAAAAAAAAAAAAAAAAAAAAAAAAAAAQEBAQEBAQEBAQEBAAAAAAAAAAAAAAAAAAAAAAAAAAABAQEBAQEBAQEBAQEAAAAAAAAAAAAAAAAAAAAAAAAAAAEBAQEBAQEBAQEBAQAAAAAAAAAAAAAAAAAAAQEBAQEBAQEBAQEBAQEBAQEBAAAAAAAAAAAAAAAAAAABAQEBAQEBAQEBAQEBAQEBAQEAAAAAAAAAAAAAAAAAAAEBAQEBAQEBAQEBAQEBAQEBAQAAAAAAAAAAAAAAAAAAAQEBAQEBAQEBAQEBAAAAAAAAAAAAAAAAAAAAAAAAAAABAQEBAQEBAQEBAQEAAAAAAAAAAAAAAAAAAAAAAAAAAAEBAQEBAQEBAQEBAQAAAAAAAAAAAAAAAAAAAQEBAQEBAQEBAQEBAQEBAQEBAAAAAAAAAAAAAAAAAAABAQEBAQEBAQEBAQEBAQEBAQEAAAAAAAAAAAAAAAAAAAEBAQEBAQEBAQEBAQEBAQEBAQAAAAAAAAAAAAAAAAAAAQEBAQEBAQEBAQEBAQEBAQEBAAAAAAAAAAAAAAAAAAABAQEBAQEBAQEBAQEBAQEBAQEAAAAAAAAAAAAAAAAAAAEBAQEBAQEBAQEBAQ==" - }, - "palette" : { - "originalArgb8888" : [ -265674 ], - "convertedRgb565" : [ -122 ] } }, "diagnostics" : [ ] @@ -816,14 +816,14 @@ "last_modified" : 1774359772460, "fingerprint" : "eeb7cc665386299403b7be1c272375d5077f3647c587f8033aa8c9275f840562", "metadata" : { + "palette" : { + "originalArgb8888" : [ -265674 ], + "convertedRgb565" : [ -122 ] + }, "tile" : { "width" : 32, "height" : 32, "paletteIndices" : "AQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAAAAAAAAAAABAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEAAAAAAAAAAAEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQAAAAAAAAAAAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAAAAAAAAAAABAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEAAAAAAAAAAAEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQAAAAAAAAAAAQEBAQEBAQEBAQEBAAAAAAAAAAAAAAAAAAAAAAAAAAABAQEBAQEBAQEBAQEAAAAAAAAAAAAAAAAAAAAAAAAAAAEBAQEBAQEBAQEBAQAAAAAAAAAAAAAAAAAAAAAAAAAAAQEBAQEBAQEBAQEBAAAAAAAAAAAAAAAAAAAAAAAAAAABAQEBAQEBAQEBAQEAAAAAAAAAAAAAAAAAAAAAAAAAAAEBAQEBAQEBAQEBAQAAAAAAAAAAAAAAAAAAAAAAAAAAAQEBAQEBAQEBAQEBAAAAAAAAAAAAAAAAAAAAAAAAAAABAQEBAQEBAQEBAQEAAAAAAAAAAAAAAAAAAAAAAAAAAAEBAQEBAQEBAQEBAQAAAAAAAAAAAAAAAAAAAQEBAQEBAQEBAQEBAQEBAQEBAAAAAAAAAAAAAAAAAAABAQEBAQEBAQEBAQEBAQEBAQEAAAAAAAAAAAAAAAAAAAEBAQEBAQEBAQEBAQEBAQEBAQAAAAAAAAAAAAAAAAAAAQEBAQEBAQEBAQEBAAAAAAAAAAAAAAAAAAAAAAAAAAABAQEBAQEBAQEBAQEAAAAAAAAAAAAAAAAAAAAAAAAAAAEBAQEBAQEBAQEBAQAAAAAAAAAAAAAAAAAAAQEBAQEBAQEBAQEBAQEBAQEBAAAAAAAAAAAAAAAAAAABAQEBAQEBAQEBAQEBAQEBAQEAAAAAAAAAAAAAAAAAAAEBAQEBAQEBAQEBAQEBAQEBAQAAAAAAAAAAAAAAAAAAAQEBAQEBAQEBAQEBAQEBAQEBAAAAAAAAAAAAAAAAAAABAQEBAQEBAQEBAQEBAQEBAQEAAAAAAAAAAAAAAAAAAAEBAQEBAQEBAQEBAQ==" - }, - "palette" : { - "originalArgb8888" : [ -265674 ], - "convertedRgb565" : [ -122 ] } }, "diagnostics" : [ ] @@ -834,14 +834,14 @@ "last_modified" : 1774359772461, "fingerprint" : "eeb7cc665386299403b7be1c272375d5077f3647c587f8033aa8c9275f840562", "metadata" : { + "palette" : { + "originalArgb8888" : [ -265674 ], + "convertedRgb565" : [ -122 ] + }, "tile" : { "width" : 32, "height" : 32, "paletteIndices" : "AQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAAAAAAAAAAABAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEAAAAAAAAAAAEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQAAAAAAAAAAAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAAAAAAAAAAABAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEAAAAAAAAAAAEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQAAAAAAAAAAAQEBAQEBAQEBAQEBAAAAAAAAAAAAAAAAAAAAAAAAAAABAQEBAQEBAQEBAQEAAAAAAAAAAAAAAAAAAAAAAAAAAAEBAQEBAQEBAQEBAQAAAAAAAAAAAAAAAAAAAAAAAAAAAQEBAQEBAQEBAQEBAAAAAAAAAAAAAAAAAAAAAAAAAAABAQEBAQEBAQEBAQEAAAAAAAAAAAAAAAAAAAAAAAAAAAEBAQEBAQEBAQEBAQAAAAAAAAAAAAAAAAAAAAAAAAAAAQEBAQEBAQEBAQEBAAAAAAAAAAAAAAAAAAAAAAAAAAABAQEBAQEBAQEBAQEAAAAAAAAAAAAAAAAAAAAAAAAAAAEBAQEBAQEBAQEBAQAAAAAAAAAAAAAAAAAAAQEBAQEBAQEBAQEBAQEBAQEBAAAAAAAAAAAAAAAAAAABAQEBAQEBAQEBAQEBAQEBAQEAAAAAAAAAAAAAAAAAAAEBAQEBAQEBAQEBAQEBAQEBAQAAAAAAAAAAAAAAAAAAAQEBAQEBAQEBAQEBAAAAAAAAAAAAAAAAAAAAAAAAAAABAQEBAQEBAQEBAQEAAAAAAAAAAAAAAAAAAAAAAAAAAAEBAQEBAQEBAQEBAQAAAAAAAAAAAAAAAAAAAQEBAQEBAQEBAQEBAQEBAQEBAAAAAAAAAAAAAAAAAAABAQEBAQEBAQEBAQEBAQEBAQEAAAAAAAAAAAAAAAAAAAEBAQEBAQEBAQEBAQEBAQEBAQAAAAAAAAAAAAAAAAAAAQEBAQEBAQEBAQEBAQEBAQEBAAAAAAAAAAAAAAAAAAABAQEBAQEBAQEBAQEBAQEBAQEAAAAAAAAAAAAAAAAAAAEBAQEBAQEBAQEBAQ==" - }, - "palette" : { - "originalArgb8888" : [ -265674 ], - "convertedRgb565" : [ -122 ] } }, "diagnostics" : [ ] @@ -852,14 +852,14 @@ "last_modified" : 1774359772463, "fingerprint" : "eeb7cc665386299403b7be1c272375d5077f3647c587f8033aa8c9275f840562", "metadata" : { + "palette" : { + "originalArgb8888" : [ -265674 ], + "convertedRgb565" : [ -122 ] + }, "tile" : { "width" : 32, "height" : 32, "paletteIndices" : "AQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAAAAAAAAAAABAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEAAAAAAAAAAAEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQAAAAAAAAAAAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAAAAAAAAAAABAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEAAAAAAAAAAAEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQAAAAAAAAAAAQEBAQEBAQEBAQEBAAAAAAAAAAAAAAAAAAAAAAAAAAABAQEBAQEBAQEBAQEAAAAAAAAAAAAAAAAAAAAAAAAAAAEBAQEBAQEBAQEBAQAAAAAAAAAAAAAAAAAAAAAAAAAAAQEBAQEBAQEBAQEBAAAAAAAAAAAAAAAAAAAAAAAAAAABAQEBAQEBAQEBAQEAAAAAAAAAAAAAAAAAAAAAAAAAAAEBAQEBAQEBAQEBAQAAAAAAAAAAAAAAAAAAAAAAAAAAAQEBAQEBAQEBAQEBAAAAAAAAAAAAAAAAAAAAAAAAAAABAQEBAQEBAQEBAQEAAAAAAAAAAAAAAAAAAAAAAAAAAAEBAQEBAQEBAQEBAQAAAAAAAAAAAAAAAAAAAQEBAQEBAQEBAQEBAQEBAQEBAAAAAAAAAAAAAAAAAAABAQEBAQEBAQEBAQEBAQEBAQEAAAAAAAAAAAAAAAAAAAEBAQEBAQEBAQEBAQEBAQEBAQAAAAAAAAAAAAAAAAAAAQEBAQEBAQEBAQEBAAAAAAAAAAAAAAAAAAAAAAAAAAABAQEBAQEBAQEBAQEAAAAAAAAAAAAAAAAAAAAAAAAAAAEBAQEBAQEBAQEBAQAAAAAAAAAAAAAAAAAAAQEBAQEBAQEBAQEBAQEBAQEBAAAAAAAAAAAAAAAAAAABAQEBAQEBAQEBAQEBAQEBAQEAAAAAAAAAAAAAAAAAAAEBAQEBAQEBAQEBAQEBAQEBAQAAAAAAAAAAAAAAAAAAAQEBAQEBAQEBAQEBAQEBAQEBAAAAAAAAAAAAAAAAAAABAQEBAQEBAQEBAQEBAQEBAQEAAAAAAAAAAAAAAAAAAAEBAQEBAQEBAQEBAQ==" - }, - "palette" : { - "originalArgb8888" : [ -265674 ], - "convertedRgb565" : [ -122 ] } }, "diagnostics" : [ ] @@ -870,14 +870,14 @@ "last_modified" : 1774359772464, "fingerprint" : "eeb7cc665386299403b7be1c272375d5077f3647c587f8033aa8c9275f840562", "metadata" : { + "palette" : { + "originalArgb8888" : [ -265674 ], + "convertedRgb565" : [ -122 ] + }, "tile" : { "width" : 32, "height" : 32, "paletteIndices" : "AQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAAAAAAAAAAABAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEAAAAAAAAAAAEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQAAAAAAAAAAAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAAAAAAAAAAABAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEAAAAAAAAAAAEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQAAAAAAAAAAAQEBAQEBAQEBAQEBAAAAAAAAAAAAAAAAAAAAAAAAAAABAQEBAQEBAQEBAQEAAAAAAAAAAAAAAAAAAAAAAAAAAAEBAQEBAQEBAQEBAQAAAAAAAAAAAAAAAAAAAAAAAAAAAQEBAQEBAQEBAQEBAAAAAAAAAAAAAAAAAAAAAAAAAAABAQEBAQEBAQEBAQEAAAAAAAAAAAAAAAAAAAAAAAAAAAEBAQEBAQEBAQEBAQAAAAAAAAAAAAAAAAAAAAAAAAAAAQEBAQEBAQEBAQEBAAAAAAAAAAAAAAAAAAAAAAAAAAABAQEBAQEBAQEBAQEAAAAAAAAAAAAAAAAAAAAAAAAAAAEBAQEBAQEBAQEBAQAAAAAAAAAAAAAAAAAAAQEBAQEBAQEBAQEBAQEBAQEBAAAAAAAAAAAAAAAAAAABAQEBAQEBAQEBAQEBAQEBAQEAAAAAAAAAAAAAAAAAAAEBAQEBAQEBAQEBAQEBAQEBAQAAAAAAAAAAAAAAAAAAAQEBAQEBAQEBAQEBAAAAAAAAAAAAAAAAAAAAAAAAAAABAQEBAQEBAQEBAQEAAAAAAAAAAAAAAAAAAAAAAAAAAAEBAQEBAQEBAQEBAQAAAAAAAAAAAAAAAAAAAQEBAQEBAQEBAQEBAQEBAQEBAAAAAAAAAAAAAAAAAAABAQEBAQEBAQEBAQEBAQEBAQEAAAAAAAAAAAAAAAAAAAEBAQEBAQEBAQEBAQEBAQEBAQAAAAAAAAAAAAAAAAAAAQEBAQEBAQEBAQEBAQEBAQEBAAAAAAAAAAAAAAAAAAABAQEBAQEBAQEBAQEBAQEBAQEAAAAAAAAAAAAAAAAAAAEBAQEBAQEBAQEBAQ==" - }, - "palette" : { - "originalArgb8888" : [ -265674 ], - "convertedRgb565" : [ -122 ] } }, "diagnostics" : [ ] @@ -888,14 +888,14 @@ "last_modified" : 1774359772465, "fingerprint" : "eeb7cc665386299403b7be1c272375d5077f3647c587f8033aa8c9275f840562", "metadata" : { + "palette" : { + "originalArgb8888" : [ -265674 ], + "convertedRgb565" : [ -122 ] + }, "tile" : { "width" : 32, "height" : 32, "paletteIndices" : "AQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAAAAAAAAAAABAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEAAAAAAAAAAAEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQAAAAAAAAAAAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAAAAAAAAAAABAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEAAAAAAAAAAAEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQAAAAAAAAAAAQEBAQEBAQEBAQEBAAAAAAAAAAAAAAAAAAAAAAAAAAABAQEBAQEBAQEBAQEAAAAAAAAAAAAAAAAAAAAAAAAAAAEBAQEBAQEBAQEBAQAAAAAAAAAAAAAAAAAAAAAAAAAAAQEBAQEBAQEBAQEBAAAAAAAAAAAAAAAAAAAAAAAAAAABAQEBAQEBAQEBAQEAAAAAAAAAAAAAAAAAAAAAAAAAAAEBAQEBAQEBAQEBAQAAAAAAAAAAAAAAAAAAAAAAAAAAAQEBAQEBAQEBAQEBAAAAAAAAAAAAAAAAAAAAAAAAAAABAQEBAQEBAQEBAQEAAAAAAAAAAAAAAAAAAAAAAAAAAAEBAQEBAQEBAQEBAQAAAAAAAAAAAAAAAAAAAQEBAQEBAQEBAQEBAQEBAQEBAAAAAAAAAAAAAAAAAAABAQEBAQEBAQEBAQEBAQEBAQEAAAAAAAAAAAAAAAAAAAEBAQEBAQEBAQEBAQEBAQEBAQAAAAAAAAAAAAAAAAAAAQEBAQEBAQEBAQEBAAAAAAAAAAAAAAAAAAAAAAAAAAABAQEBAQEBAQEBAQEAAAAAAAAAAAAAAAAAAAAAAAAAAAEBAQEBAQEBAQEBAQAAAAAAAAAAAAAAAAAAAQEBAQEBAQEBAQEBAQEBAQEBAAAAAAAAAAAAAAAAAAABAQEBAQEBAQEBAQEBAQEBAQEAAAAAAAAAAAAAAAAAAAEBAQEBAQEBAQEBAQEBAQEBAQAAAAAAAAAAAAAAAAAAAQEBAQEBAQEBAQEBAQEBAQEBAAAAAAAAAAAAAAAAAAABAQEBAQEBAQEBAQEBAQEBAQEAAAAAAAAAAAAAAAAAAAEBAQEBAQEBAQEBAQ==" - }, - "palette" : { - "originalArgb8888" : [ -265674 ], - "convertedRgb565" : [ -122 ] } }, "diagnostics" : [ ] @@ -906,14 +906,14 @@ "last_modified" : 1774359772467, "fingerprint" : "eeb7cc665386299403b7be1c272375d5077f3647c587f8033aa8c9275f840562", "metadata" : { + "palette" : { + "originalArgb8888" : [ -265674 ], + "convertedRgb565" : [ -122 ] + }, "tile" : { "width" : 32, "height" : 32, "paletteIndices" : "AQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAAAAAAAAAAABAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEAAAAAAAAAAAEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQAAAAAAAAAAAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAAAAAAAAAAABAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEAAAAAAAAAAAEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQAAAAAAAAAAAQEBAQEBAQEBAQEBAAAAAAAAAAAAAAAAAAAAAAAAAAABAQEBAQEBAQEBAQEAAAAAAAAAAAAAAAAAAAAAAAAAAAEBAQEBAQEBAQEBAQAAAAAAAAAAAAAAAAAAAAAAAAAAAQEBAQEBAQEBAQEBAAAAAAAAAAAAAAAAAAAAAAAAAAABAQEBAQEBAQEBAQEAAAAAAAAAAAAAAAAAAAAAAAAAAAEBAQEBAQEBAQEBAQAAAAAAAAAAAAAAAAAAAAAAAAAAAQEBAQEBAQEBAQEBAAAAAAAAAAAAAAAAAAAAAAAAAAABAQEBAQEBAQEBAQEAAAAAAAAAAAAAAAAAAAAAAAAAAAEBAQEBAQEBAQEBAQAAAAAAAAAAAAAAAAAAAQEBAQEBAQEBAQEBAQEBAQEBAAAAAAAAAAAAAAAAAAABAQEBAQEBAQEBAQEBAQEBAQEAAAAAAAAAAAAAAAAAAAEBAQEBAQEBAQEBAQEBAQEBAQAAAAAAAAAAAAAAAAAAAQEBAQEBAQEBAQEBAAAAAAAAAAAAAAAAAAAAAAAAAAABAQEBAQEBAQEBAQEAAAAAAAAAAAAAAAAAAAAAAAAAAAEBAQEBAQEBAQEBAQAAAAAAAAAAAAAAAAAAAQEBAQEBAQEBAQEBAQEBAQEBAAAAAAAAAAAAAAAAAAABAQEBAQEBAQEBAQEBAQEBAQEAAAAAAAAAAAAAAAAAAAEBAQEBAQEBAQEBAQEBAQEBAQAAAAAAAAAAAAAAAAAAAQEBAQEBAQEBAQEBAQEBAQEBAAAAAAAAAAAAAAAAAAABAQEBAQEBAQEBAQEBAQEBAQEAAAAAAAAAAAAAAAAAAAEBAQEBAQEBAQEBAQ==" - }, - "palette" : { - "originalArgb8888" : [ -265674 ], - "convertedRgb565" : [ -122 ] } }, "diagnostics" : [ ] @@ -924,14 +924,14 @@ "last_modified" : 1774359772468, "fingerprint" : "eeb7cc665386299403b7be1c272375d5077f3647c587f8033aa8c9275f840562", "metadata" : { + "palette" : { + "originalArgb8888" : [ -265674 ], + "convertedRgb565" : [ -122 ] + }, "tile" : { "width" : 32, "height" : 32, "paletteIndices" : "AQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAAAAAAAAAAABAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEAAAAAAAAAAAEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQAAAAAAAAAAAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAAAAAAAAAAABAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEAAAAAAAAAAAEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQAAAAAAAAAAAQEBAQEBAQEBAQEBAAAAAAAAAAAAAAAAAAAAAAAAAAABAQEBAQEBAQEBAQEAAAAAAAAAAAAAAAAAAAAAAAAAAAEBAQEBAQEBAQEBAQAAAAAAAAAAAAAAAAAAAAAAAAAAAQEBAQEBAQEBAQEBAAAAAAAAAAAAAAAAAAAAAAAAAAABAQEBAQEBAQEBAQEAAAAAAAAAAAAAAAAAAAAAAAAAAAEBAQEBAQEBAQEBAQAAAAAAAAAAAAAAAAAAAAAAAAAAAQEBAQEBAQEBAQEBAAAAAAAAAAAAAAAAAAAAAAAAAAABAQEBAQEBAQEBAQEAAAAAAAAAAAAAAAAAAAAAAAAAAAEBAQEBAQEBAQEBAQAAAAAAAAAAAAAAAAAAAQEBAQEBAQEBAQEBAQEBAQEBAAAAAAAAAAAAAAAAAAABAQEBAQEBAQEBAQEBAQEBAQEAAAAAAAAAAAAAAAAAAAEBAQEBAQEBAQEBAQEBAQEBAQAAAAAAAAAAAAAAAAAAAQEBAQEBAQEBAQEBAAAAAAAAAAAAAAAAAAAAAAAAAAABAQEBAQEBAQEBAQEAAAAAAAAAAAAAAAAAAAAAAAAAAAEBAQEBAQEBAQEBAQAAAAAAAAAAAAAAAAAAAQEBAQEBAQEBAQEBAQEBAQEBAAAAAAAAAAAAAAAAAAABAQEBAQEBAQEBAQEBAQEBAQEAAAAAAAAAAAAAAAAAAAEBAQEBAQEBAQEBAQEBAQEBAQAAAAAAAAAAAAAAAAAAAQEBAQEBAQEBAQEBAQEBAQEBAAAAAAAAAAAAAAAAAAABAQEBAQEBAQEBAQEBAQEBAQEAAAAAAAAAAAAAAAAAAAEBAQEBAQEBAQEBAQ==" - }, - "palette" : { - "originalArgb8888" : [ -265674 ], - "convertedRgb565" : [ -122 ] } }, "diagnostics" : [ ] @@ -942,14 +942,14 @@ "last_modified" : 1774359772470, "fingerprint" : "eeb7cc665386299403b7be1c272375d5077f3647c587f8033aa8c9275f840562", "metadata" : { + "palette" : { + "originalArgb8888" : [ -265674 ], + "convertedRgb565" : [ -122 ] + }, "tile" : { "width" : 32, "height" : 32, "paletteIndices" : "AQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAAAAAAAAAAABAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEAAAAAAAAAAAEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQAAAAAAAAAAAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAAAAAAAAAAABAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEAAAAAAAAAAAEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQAAAAAAAAAAAQEBAQEBAQEBAQEBAAAAAAAAAAAAAAAAAAAAAAAAAAABAQEBAQEBAQEBAQEAAAAAAAAAAAAAAAAAAAAAAAAAAAEBAQEBAQEBAQEBAQAAAAAAAAAAAAAAAAAAAAAAAAAAAQEBAQEBAQEBAQEBAAAAAAAAAAAAAAAAAAAAAAAAAAABAQEBAQEBAQEBAQEAAAAAAAAAAAAAAAAAAAAAAAAAAAEBAQEBAQEBAQEBAQAAAAAAAAAAAAAAAAAAAAAAAAAAAQEBAQEBAQEBAQEBAAAAAAAAAAAAAAAAAAAAAAAAAAABAQEBAQEBAQEBAQEAAAAAAAAAAAAAAAAAAAAAAAAAAAEBAQEBAQEBAQEBAQAAAAAAAAAAAAAAAAAAAQEBAQEBAQEBAQEBAQEBAQEBAAAAAAAAAAAAAAAAAAABAQEBAQEBAQEBAQEBAQEBAQEAAAAAAAAAAAAAAAAAAAEBAQEBAQEBAQEBAQEBAQEBAQAAAAAAAAAAAAAAAAAAAQEBAQEBAQEBAQEBAAAAAAAAAAAAAAAAAAAAAAAAAAABAQEBAQEBAQEBAQEAAAAAAAAAAAAAAAAAAAAAAAAAAAEBAQEBAQEBAQEBAQAAAAAAAAAAAAAAAAAAAQEBAQEBAQEBAQEBAQEBAQEBAAAAAAAAAAAAAAAAAAABAQEBAQEBAQEBAQEBAQEBAQEAAAAAAAAAAAAAAAAAAAEBAQEBAQEBAQEBAQEBAQEBAQAAAAAAAAAAAAAAAAAAAQEBAQEBAQEBAQEBAQEBAQEBAAAAAAAAAAAAAAAAAAABAQEBAQEBAQEBAQEBAQEBAQEAAAAAAAAAAAAAAAAAAAEBAQEBAQEBAQEBAQ==" - }, - "palette" : { - "originalArgb8888" : [ -265674 ], - "convertedRgb565" : [ -122 ] } }, "diagnostics" : [ ] @@ -960,14 +960,14 @@ "last_modified" : 1774359772474, "fingerprint" : "eeb7cc665386299403b7be1c272375d5077f3647c587f8033aa8c9275f840562", "metadata" : { + "palette" : { + "originalArgb8888" : [ -265674 ], + "convertedRgb565" : [ -122 ] + }, "tile" : { "width" : 32, "height" : 32, "paletteIndices" : "AQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAAAAAAAAAAABAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEAAAAAAAAAAAEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQAAAAAAAAAAAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAAAAAAAAAAABAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEAAAAAAAAAAAEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQAAAAAAAAAAAQEBAQEBAQEBAQEBAAAAAAAAAAAAAAAAAAAAAAAAAAABAQEBAQEBAQEBAQEAAAAAAAAAAAAAAAAAAAAAAAAAAAEBAQEBAQEBAQEBAQAAAAAAAAAAAAAAAAAAAAAAAAAAAQEBAQEBAQEBAQEBAAAAAAAAAAAAAAAAAAAAAAAAAAABAQEBAQEBAQEBAQEAAAAAAAAAAAAAAAAAAAAAAAAAAAEBAQEBAQEBAQEBAQAAAAAAAAAAAAAAAAAAAAAAAAAAAQEBAQEBAQEBAQEBAAAAAAAAAAAAAAAAAAAAAAAAAAABAQEBAQEBAQEBAQEAAAAAAAAAAAAAAAAAAAAAAAAAAAEBAQEBAQEBAQEBAQAAAAAAAAAAAAAAAAAAAQEBAQEBAQEBAQEBAQEBAQEBAAAAAAAAAAAAAAAAAAABAQEBAQEBAQEBAQEBAQEBAQEAAAAAAAAAAAAAAAAAAAEBAQEBAQEBAQEBAQEBAQEBAQAAAAAAAAAAAAAAAAAAAQEBAQEBAQEBAQEBAAAAAAAAAAAAAAAAAAAAAAAAAAABAQEBAQEBAQEBAQEAAAAAAAAAAAAAAAAAAAAAAAAAAAEBAQEBAQEBAQEBAQAAAAAAAAAAAAAAAAAAAQEBAQEBAQEBAQEBAQEBAQEBAAAAAAAAAAAAAAAAAAABAQEBAQEBAQEBAQEBAQEBAQEAAAAAAAAAAAAAAAAAAAEBAQEBAQEBAQEBAQEBAQEBAQAAAAAAAAAAAAAAAAAAAQEBAQEBAQEBAQEBAQEBAQEBAAAAAAAAAAAAAAAAAAABAQEBAQEBAQEBAQEBAQEBAQEAAAAAAAAAAAAAAAAAAAEBAQEBAQEBAQEBAQ==" - }, - "palette" : { - "originalArgb8888" : [ -265674 ], - "convertedRgb565" : [ -122 ] } }, "diagnostics" : [ ] @@ -978,14 +978,14 @@ "last_modified" : 1774359772476, "fingerprint" : "eeb7cc665386299403b7be1c272375d5077f3647c587f8033aa8c9275f840562", "metadata" : { + "palette" : { + "originalArgb8888" : [ -265674 ], + "convertedRgb565" : [ -122 ] + }, "tile" : { "width" : 32, "height" : 32, "paletteIndices" : "AQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAAAAAAAAAAABAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEAAAAAAAAAAAEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQAAAAAAAAAAAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAAAAAAAAAAABAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEAAAAAAAAAAAEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQAAAAAAAAAAAQEBAQEBAQEBAQEBAAAAAAAAAAAAAAAAAAAAAAAAAAABAQEBAQEBAQEBAQEAAAAAAAAAAAAAAAAAAAAAAAAAAAEBAQEBAQEBAQEBAQAAAAAAAAAAAAAAAAAAAAAAAAAAAQEBAQEBAQEBAQEBAAAAAAAAAAAAAAAAAAAAAAAAAAABAQEBAQEBAQEBAQEAAAAAAAAAAAAAAAAAAAAAAAAAAAEBAQEBAQEBAQEBAQAAAAAAAAAAAAAAAAAAAAAAAAAAAQEBAQEBAQEBAQEBAAAAAAAAAAAAAAAAAAAAAAAAAAABAQEBAQEBAQEBAQEAAAAAAAAAAAAAAAAAAAAAAAAAAAEBAQEBAQEBAQEBAQAAAAAAAAAAAAAAAAAAAQEBAQEBAQEBAQEBAQEBAQEBAAAAAAAAAAAAAAAAAAABAQEBAQEBAQEBAQEBAQEBAQEAAAAAAAAAAAAAAAAAAAEBAQEBAQEBAQEBAQEBAQEBAQAAAAAAAAAAAAAAAAAAAQEBAQEBAQEBAQEBAAAAAAAAAAAAAAAAAAAAAAAAAAABAQEBAQEBAQEBAQEAAAAAAAAAAAAAAAAAAAAAAAAAAAEBAQEBAQEBAQEBAQAAAAAAAAAAAAAAAAAAAQEBAQEBAQEBAQEBAQEBAQEBAAAAAAAAAAAAAAAAAAABAQEBAQEBAQEBAQEBAQEBAQEAAAAAAAAAAAAAAAAAAAEBAQEBAQEBAQEBAQEBAQEBAQAAAAAAAAAAAAAAAAAAAQEBAQEBAQEBAQEBAQEBAQEBAAAAAAAAAAAAAAAAAAABAQEBAQEBAQEBAQEBAQEBAQEAAAAAAAAAAAAAAAAAAAEBAQEBAQEBAQEBAQ==" - }, - "palette" : { - "originalArgb8888" : [ -265674 ], - "convertedRgb565" : [ -122 ] } }, "diagnostics" : [ ] @@ -996,14 +996,14 @@ "last_modified" : 1774359772478, "fingerprint" : "eeb7cc665386299403b7be1c272375d5077f3647c587f8033aa8c9275f840562", "metadata" : { + "palette" : { + "originalArgb8888" : [ -265674 ], + "convertedRgb565" : [ -122 ] + }, "tile" : { "width" : 32, "height" : 32, "paletteIndices" : "AQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAAAAAAAAAAABAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEAAAAAAAAAAAEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQAAAAAAAAAAAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAAAAAAAAAAABAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEAAAAAAAAAAAEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQAAAAAAAAAAAQEBAQEBAQEBAQEBAAAAAAAAAAAAAAAAAAAAAAAAAAABAQEBAQEBAQEBAQEAAAAAAAAAAAAAAAAAAAAAAAAAAAEBAQEBAQEBAQEBAQAAAAAAAAAAAAAAAAAAAAAAAAAAAQEBAQEBAQEBAQEBAAAAAAAAAAAAAAAAAAAAAAAAAAABAQEBAQEBAQEBAQEAAAAAAAAAAAAAAAAAAAAAAAAAAAEBAQEBAQEBAQEBAQAAAAAAAAAAAAAAAAAAAAAAAAAAAQEBAQEBAQEBAQEBAAAAAAAAAAAAAAAAAAAAAAAAAAABAQEBAQEBAQEBAQEAAAAAAAAAAAAAAAAAAAAAAAAAAAEBAQEBAQEBAQEBAQAAAAAAAAAAAAAAAAAAAQEBAQEBAQEBAQEBAQEBAQEBAAAAAAAAAAAAAAAAAAABAQEBAQEBAQEBAQEBAQEBAQEAAAAAAAAAAAAAAAAAAAEBAQEBAQEBAQEBAQEBAQEBAQAAAAAAAAAAAAAAAAAAAQEBAQEBAQEBAQEBAAAAAAAAAAAAAAAAAAAAAAAAAAABAQEBAQEBAQEBAQEAAAAAAAAAAAAAAAAAAAAAAAAAAAEBAQEBAQEBAQEBAQAAAAAAAAAAAAAAAAAAAQEBAQEBAQEBAQEBAQEBAQEBAAAAAAAAAAAAAAAAAAABAQEBAQEBAQEBAQEBAQEBAQEAAAAAAAAAAAAAAAAAAAEBAQEBAQEBAQEBAQEBAQEBAQAAAAAAAAAAAAAAAAAAAQEBAQEBAQEBAQEBAQEBAQEBAAAAAAAAAAAAAAAAAAABAQEBAQEBAQEBAQEBAQEBAQEAAAAAAAAAAAAAAAAAAAEBAQEBAQEBAQEBAQ==" - }, - "palette" : { - "originalArgb8888" : [ -265674 ], - "convertedRgb565" : [ -122 ] } }, "diagnostics" : [ ] @@ -1014,14 +1014,14 @@ "last_modified" : 1774359772479, "fingerprint" : "eeb7cc665386299403b7be1c272375d5077f3647c587f8033aa8c9275f840562", "metadata" : { + "palette" : { + "originalArgb8888" : [ -265674 ], + "convertedRgb565" : [ -122 ] + }, "tile" : { "width" : 32, "height" : 32, "paletteIndices" : "AQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAAAAAAAAAAABAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEAAAAAAAAAAAEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQAAAAAAAAAAAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAAAAAAAAAAABAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEAAAAAAAAAAAEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQAAAAAAAAAAAQEBAQEBAQEBAQEBAAAAAAAAAAAAAAAAAAAAAAAAAAABAQEBAQEBAQEBAQEAAAAAAAAAAAAAAAAAAAAAAAAAAAEBAQEBAQEBAQEBAQAAAAAAAAAAAAAAAAAAAAAAAAAAAQEBAQEBAQEBAQEBAAAAAAAAAAAAAAAAAAAAAAAAAAABAQEBAQEBAQEBAQEAAAAAAAAAAAAAAAAAAAAAAAAAAAEBAQEBAQEBAQEBAQAAAAAAAAAAAAAAAAAAAAAAAAAAAQEBAQEBAQEBAQEBAAAAAAAAAAAAAAAAAAAAAAAAAAABAQEBAQEBAQEBAQEAAAAAAAAAAAAAAAAAAAAAAAAAAAEBAQEBAQEBAQEBAQAAAAAAAAAAAAAAAAAAAQEBAQEBAQEBAQEBAQEBAQEBAAAAAAAAAAAAAAAAAAABAQEBAQEBAQEBAQEBAQEBAQEAAAAAAAAAAAAAAAAAAAEBAQEBAQEBAQEBAQEBAQEBAQAAAAAAAAAAAAAAAAAAAQEBAQEBAQEBAQEBAAAAAAAAAAAAAAAAAAAAAAAAAAABAQEBAQEBAQEBAQEAAAAAAAAAAAAAAAAAAAAAAAAAAAEBAQEBAQEBAQEBAQAAAAAAAAAAAAAAAAAAAQEBAQEBAQEBAQEBAQEBAQEBAAAAAAAAAAAAAAAAAAABAQEBAQEBAQEBAQEBAQEBAQEAAAAAAAAAAAAAAAAAAAEBAQEBAQEBAQEBAQEBAQEBAQAAAAAAAAAAAAAAAAAAAQEBAQEBAQEBAQEBAQEBAQEBAAAAAAAAAAAAAAAAAAABAQEBAQEBAQEBAQEBAQEBAQEAAAAAAAAAAAAAAAAAAAEBAQEBAQEBAQEBAQ==" - }, - "palette" : { - "originalArgb8888" : [ -265674 ], - "convertedRgb565" : [ -122 ] } }, "diagnostics" : [ ] @@ -1032,14 +1032,14 @@ "last_modified" : 1774359772481, "fingerprint" : "eeb7cc665386299403b7be1c272375d5077f3647c587f8033aa8c9275f840562", "metadata" : { + "palette" : { + "originalArgb8888" : [ -265674 ], + "convertedRgb565" : [ -122 ] + }, "tile" : { "width" : 32, "height" : 32, "paletteIndices" : "AQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAAAAAAAAAAABAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEAAAAAAAAAAAEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQAAAAAAAAAAAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAAAAAAAAAAABAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEAAAAAAAAAAAEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQAAAAAAAAAAAQEBAQEBAQEBAQEBAAAAAAAAAAAAAAAAAAAAAAAAAAABAQEBAQEBAQEBAQEAAAAAAAAAAAAAAAAAAAAAAAAAAAEBAQEBAQEBAQEBAQAAAAAAAAAAAAAAAAAAAAAAAAAAAQEBAQEBAQEBAQEBAAAAAAAAAAAAAAAAAAAAAAAAAAABAQEBAQEBAQEBAQEAAAAAAAAAAAAAAAAAAAAAAAAAAAEBAQEBAQEBAQEBAQAAAAAAAAAAAAAAAAAAAAAAAAAAAQEBAQEBAQEBAQEBAAAAAAAAAAAAAAAAAAAAAAAAAAABAQEBAQEBAQEBAQEAAAAAAAAAAAAAAAAAAAAAAAAAAAEBAQEBAQEBAQEBAQAAAAAAAAAAAAAAAAAAAQEBAQEBAQEBAQEBAQEBAQEBAAAAAAAAAAAAAAAAAAABAQEBAQEBAQEBAQEBAQEBAQEAAAAAAAAAAAAAAAAAAAEBAQEBAQEBAQEBAQEBAQEBAQAAAAAAAAAAAAAAAAAAAQEBAQEBAQEBAQEBAAAAAAAAAAAAAAAAAAAAAAAAAAABAQEBAQEBAQEBAQEAAAAAAAAAAAAAAAAAAAAAAAAAAAEBAQEBAQEBAQEBAQAAAAAAAAAAAAAAAAAAAQEBAQEBAQEBAQEBAQEBAQEBAAAAAAAAAAAAAAAAAAABAQEBAQEBAQEBAQEBAQEBAQEAAAAAAAAAAAAAAAAAAAEBAQEBAQEBAQEBAQEBAQEBAQAAAAAAAAAAAAAAAAAAAQEBAQEBAQEBAQEBAQEBAQEBAAAAAAAAAAAAAAAAAAABAQEBAQEBAQEBAQEBAQEBAQEAAAAAAAAAAAAAAAAAAAEBAQEBAQEBAQEBAQ==" - }, - "palette" : { - "originalArgb8888" : [ -265674 ], - "convertedRgb565" : [ -122 ] } }, "diagnostics" : [ ] @@ -1050,14 +1050,14 @@ "last_modified" : 1774359772482, "fingerprint" : "eeb7cc665386299403b7be1c272375d5077f3647c587f8033aa8c9275f840562", "metadata" : { + "palette" : { + "originalArgb8888" : [ -265674 ], + "convertedRgb565" : [ -122 ] + }, "tile" : { "width" : 32, "height" : 32, "paletteIndices" : "AQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAAAAAAAAAAABAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEAAAAAAAAAAAEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQAAAAAAAAAAAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAAAAAAAAAAABAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEAAAAAAAAAAAEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQAAAAAAAAAAAQEBAQEBAQEBAQEBAAAAAAAAAAAAAAAAAAAAAAAAAAABAQEBAQEBAQEBAQEAAAAAAAAAAAAAAAAAAAAAAAAAAAEBAQEBAQEBAQEBAQAAAAAAAAAAAAAAAAAAAAAAAAAAAQEBAQEBAQEBAQEBAAAAAAAAAAAAAAAAAAAAAAAAAAABAQEBAQEBAQEBAQEAAAAAAAAAAAAAAAAAAAAAAAAAAAEBAQEBAQEBAQEBAQAAAAAAAAAAAAAAAAAAAAAAAAAAAQEBAQEBAQEBAQEBAAAAAAAAAAAAAAAAAAAAAAAAAAABAQEBAQEBAQEBAQEAAAAAAAAAAAAAAAAAAAAAAAAAAAEBAQEBAQEBAQEBAQAAAAAAAAAAAAAAAAAAAQEBAQEBAQEBAQEBAQEBAQEBAAAAAAAAAAAAAAAAAAABAQEBAQEBAQEBAQEBAQEBAQEAAAAAAAAAAAAAAAAAAAEBAQEBAQEBAQEBAQEBAQEBAQAAAAAAAAAAAAAAAAAAAQEBAQEBAQEBAQEBAAAAAAAAAAAAAAAAAAAAAAAAAAABAQEBAQEBAQEBAQEAAAAAAAAAAAAAAAAAAAAAAAAAAAEBAQEBAQEBAQEBAQAAAAAAAAAAAAAAAAAAAQEBAQEBAQEBAQEBAQEBAQEBAAAAAAAAAAAAAAAAAAABAQEBAQEBAQEBAQEBAQEBAQEAAAAAAAAAAAAAAAAAAAEBAQEBAQEBAQEBAQEBAQEBAQAAAAAAAAAAAAAAAAAAAQEBAQEBAQEBAQEBAQEBAQEBAAAAAAAAAAAAAAAAAAABAQEBAQEBAQEBAQEBAQEBAQEAAAAAAAAAAAAAAAAAAAEBAQEBAQEBAQEBAQ==" - }, - "palette" : { - "originalArgb8888" : [ -265674 ], - "convertedRgb565" : [ -122 ] } }, "diagnostics" : [ ] @@ -1068,14 +1068,14 @@ "last_modified" : 1774359772483, "fingerprint" : "eeb7cc665386299403b7be1c272375d5077f3647c587f8033aa8c9275f840562", "metadata" : { + "palette" : { + "originalArgb8888" : [ -265674 ], + "convertedRgb565" : [ -122 ] + }, "tile" : { "width" : 32, "height" : 32, "paletteIndices" : "AQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAAAAAAAAAAABAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEAAAAAAAAAAAEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQAAAAAAAAAAAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAAAAAAAAAAABAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEAAAAAAAAAAAEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQAAAAAAAAAAAQEBAQEBAQEBAQEBAAAAAAAAAAAAAAAAAAAAAAAAAAABAQEBAQEBAQEBAQEAAAAAAAAAAAAAAAAAAAAAAAAAAAEBAQEBAQEBAQEBAQAAAAAAAAAAAAAAAAAAAAAAAAAAAQEBAQEBAQEBAQEBAAAAAAAAAAAAAAAAAAAAAAAAAAABAQEBAQEBAQEBAQEAAAAAAAAAAAAAAAAAAAAAAAAAAAEBAQEBAQEBAQEBAQAAAAAAAAAAAAAAAAAAAAAAAAAAAQEBAQEBAQEBAQEBAAAAAAAAAAAAAAAAAAAAAAAAAAABAQEBAQEBAQEBAQEAAAAAAAAAAAAAAAAAAAAAAAAAAAEBAQEBAQEBAQEBAQAAAAAAAAAAAAAAAAAAAQEBAQEBAQEBAQEBAQEBAQEBAAAAAAAAAAAAAAAAAAABAQEBAQEBAQEBAQEBAQEBAQEAAAAAAAAAAAAAAAAAAAEBAQEBAQEBAQEBAQEBAQEBAQAAAAAAAAAAAAAAAAAAAQEBAQEBAQEBAQEBAAAAAAAAAAAAAAAAAAAAAAAAAAABAQEBAQEBAQEBAQEAAAAAAAAAAAAAAAAAAAAAAAAAAAEBAQEBAQEBAQEBAQAAAAAAAAAAAAAAAAAAAQEBAQEBAQEBAQEBAQEBAQEBAAAAAAAAAAAAAAAAAAABAQEBAQEBAQEBAQEBAQEBAQEAAAAAAAAAAAAAAAAAAAEBAQEBAQEBAQEBAQEBAQEBAQAAAAAAAAAAAAAAAAAAAQEBAQEBAQEBAQEBAQEBAQEBAAAAAAAAAAAAAAAAAAABAQEBAQEBAQEBAQEBAQEBAQEAAAAAAAAAAAAAAAAAAAEBAQEBAQEBAQEBAQ==" - }, - "palette" : { - "originalArgb8888" : [ -265674 ], - "convertedRgb565" : [ -122 ] } }, "diagnostics" : [ ] @@ -1086,14 +1086,14 @@ "last_modified" : 1774359772484, "fingerprint" : "eeb7cc665386299403b7be1c272375d5077f3647c587f8033aa8c9275f840562", "metadata" : { + "palette" : { + "originalArgb8888" : [ -265674 ], + "convertedRgb565" : [ -122 ] + }, "tile" : { "width" : 32, "height" : 32, "paletteIndices" : "AQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAAAAAAAAAAABAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEAAAAAAAAAAAEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQAAAAAAAAAAAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAAAAAAAAAAABAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEAAAAAAAAAAAEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQAAAAAAAAAAAQEBAQEBAQEBAQEBAAAAAAAAAAAAAAAAAAAAAAAAAAABAQEBAQEBAQEBAQEAAAAAAAAAAAAAAAAAAAAAAAAAAAEBAQEBAQEBAQEBAQAAAAAAAAAAAAAAAAAAAAAAAAAAAQEBAQEBAQEBAQEBAAAAAAAAAAAAAAAAAAAAAAAAAAABAQEBAQEBAQEBAQEAAAAAAAAAAAAAAAAAAAAAAAAAAAEBAQEBAQEBAQEBAQAAAAAAAAAAAAAAAAAAAAAAAAAAAQEBAQEBAQEBAQEBAAAAAAAAAAAAAAAAAAAAAAAAAAABAQEBAQEBAQEBAQEAAAAAAAAAAAAAAAAAAAAAAAAAAAEBAQEBAQEBAQEBAQAAAAAAAAAAAAAAAAAAAQEBAQEBAQEBAQEBAQEBAQEBAAAAAAAAAAAAAAAAAAABAQEBAQEBAQEBAQEBAQEBAQEAAAAAAAAAAAAAAAAAAAEBAQEBAQEBAQEBAQEBAQEBAQAAAAAAAAAAAAAAAAAAAQEBAQEBAQEBAQEBAAAAAAAAAAAAAAAAAAAAAAAAAAABAQEBAQEBAQEBAQEAAAAAAAAAAAAAAAAAAAAAAAAAAAEBAQEBAQEBAQEBAQAAAAAAAAAAAAAAAAAAAQEBAQEBAQEBAQEBAQEBAQEBAAAAAAAAAAAAAAAAAAABAQEBAQEBAQEBAQEBAQEBAQEAAAAAAAAAAAAAAAAAAAEBAQEBAQEBAQEBAQEBAQEBAQAAAAAAAAAAAAAAAAAAAQEBAQEBAQEBAQEBAQEBAQEBAAAAAAAAAAAAAAAAAAABAQEBAQEBAQEBAQEBAQEBAQEAAAAAAAAAAAAAAAAAAAEBAQEBAQEBAQEBAQ==" - }, - "palette" : { - "originalArgb8888" : [ -265674 ], - "convertedRgb565" : [ -122 ] } }, "diagnostics" : [ ] @@ -1104,14 +1104,14 @@ "last_modified" : 1774359772485, "fingerprint" : "eeb7cc665386299403b7be1c272375d5077f3647c587f8033aa8c9275f840562", "metadata" : { + "palette" : { + "originalArgb8888" : [ -265674 ], + "convertedRgb565" : [ -122 ] + }, "tile" : { "width" : 32, "height" : 32, "paletteIndices" : "AQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAAAAAAAAAAABAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEAAAAAAAAAAAEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQAAAAAAAAAAAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAAAAAAAAAAABAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEAAAAAAAAAAAEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQAAAAAAAAAAAQEBAQEBAQEBAQEBAAAAAAAAAAAAAAAAAAAAAAAAAAABAQEBAQEBAQEBAQEAAAAAAAAAAAAAAAAAAAAAAAAAAAEBAQEBAQEBAQEBAQAAAAAAAAAAAAAAAAAAAAAAAAAAAQEBAQEBAQEBAQEBAAAAAAAAAAAAAAAAAAAAAAAAAAABAQEBAQEBAQEBAQEAAAAAAAAAAAAAAAAAAAAAAAAAAAEBAQEBAQEBAQEBAQAAAAAAAAAAAAAAAAAAAAAAAAAAAQEBAQEBAQEBAQEBAAAAAAAAAAAAAAAAAAAAAAAAAAABAQEBAQEBAQEBAQEAAAAAAAAAAAAAAAAAAAAAAAAAAAEBAQEBAQEBAQEBAQAAAAAAAAAAAAAAAAAAAQEBAQEBAQEBAQEBAQEBAQEBAAAAAAAAAAAAAAAAAAABAQEBAQEBAQEBAQEBAQEBAQEAAAAAAAAAAAAAAAAAAAEBAQEBAQEBAQEBAQEBAQEBAQAAAAAAAAAAAAAAAAAAAQEBAQEBAQEBAQEBAAAAAAAAAAAAAAAAAAAAAAAAAAABAQEBAQEBAQEBAQEAAAAAAAAAAAAAAAAAAAAAAAAAAAEBAQEBAQEBAQEBAQAAAAAAAAAAAAAAAAAAAQEBAQEBAQEBAQEBAQEBAQEBAAAAAAAAAAAAAAAAAAABAQEBAQEBAQEBAQEBAQEBAQEAAAAAAAAAAAAAAAAAAAEBAQEBAQEBAQEBAQEBAQEBAQAAAAAAAAAAAAAAAAAAAQEBAQEBAQEBAQEBAQEBAQEBAAAAAAAAAAAAAAAAAAABAQEBAQEBAQEBAQEBAQEBAQEAAAAAAAAAAAAAAAAAAAEBAQEBAQEBAQEBAQ==" - }, - "palette" : { - "originalArgb8888" : [ -265674 ], - "convertedRgb565" : [ -122 ] } }, "diagnostics" : [ ] @@ -1122,14 +1122,14 @@ "last_modified" : 1774359772487, "fingerprint" : "eeb7cc665386299403b7be1c272375d5077f3647c587f8033aa8c9275f840562", "metadata" : { + "palette" : { + "originalArgb8888" : [ -265674 ], + "convertedRgb565" : [ -122 ] + }, "tile" : { "width" : 32, "height" : 32, "paletteIndices" : "AQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAAAAAAAAAAABAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEAAAAAAAAAAAEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQAAAAAAAAAAAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAAAAAAAAAAABAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEAAAAAAAAAAAEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQAAAAAAAAAAAQEBAQEBAQEBAQEBAAAAAAAAAAAAAAAAAAAAAAAAAAABAQEBAQEBAQEBAQEAAAAAAAAAAAAAAAAAAAAAAAAAAAEBAQEBAQEBAQEBAQAAAAAAAAAAAAAAAAAAAAAAAAAAAQEBAQEBAQEBAQEBAAAAAAAAAAAAAAAAAAAAAAAAAAABAQEBAQEBAQEBAQEAAAAAAAAAAAAAAAAAAAAAAAAAAAEBAQEBAQEBAQEBAQAAAAAAAAAAAAAAAAAAAAAAAAAAAQEBAQEBAQEBAQEBAAAAAAAAAAAAAAAAAAAAAAAAAAABAQEBAQEBAQEBAQEAAAAAAAAAAAAAAAAAAAAAAAAAAAEBAQEBAQEBAQEBAQAAAAAAAAAAAAAAAAAAAQEBAQEBAQEBAQEBAQEBAQEBAAAAAAAAAAAAAAAAAAABAQEBAQEBAQEBAQEBAQEBAQEAAAAAAAAAAAAAAAAAAAEBAQEBAQEBAQEBAQEBAQEBAQAAAAAAAAAAAAAAAAAAAQEBAQEBAQEBAQEBAAAAAAAAAAAAAAAAAAAAAAAAAAABAQEBAQEBAQEBAQEAAAAAAAAAAAAAAAAAAAAAAAAAAAEBAQEBAQEBAQEBAQAAAAAAAAAAAAAAAAAAAQEBAQEBAQEBAQEBAQEBAQEBAAAAAAAAAAAAAAAAAAABAQEBAQEBAQEBAQEBAQEBAQEAAAAAAAAAAAAAAAAAAAEBAQEBAQEBAQEBAQEBAQEBAQAAAAAAAAAAAAAAAAAAAQEBAQEBAQEBAQEBAQEBAQEBAAAAAAAAAAAAAAAAAAABAQEBAQEBAQEBAQEBAQEBAQEAAAAAAAAAAAAAAAAAAAEBAQEBAQEBAQEBAQ==" - }, - "palette" : { - "originalArgb8888" : [ -265674 ], - "convertedRgb565" : [ -122 ] } }, "diagnostics" : [ ] @@ -1140,14 +1140,14 @@ "last_modified" : 1774359772488, "fingerprint" : "eeb7cc665386299403b7be1c272375d5077f3647c587f8033aa8c9275f840562", "metadata" : { + "palette" : { + "originalArgb8888" : [ -265674 ], + "convertedRgb565" : [ -122 ] + }, "tile" : { "width" : 32, "height" : 32, "paletteIndices" : "AQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAAAAAAAAAAABAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEAAAAAAAAAAAEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQAAAAAAAAAAAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAAAAAAAAAAABAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEAAAAAAAAAAAEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQAAAAAAAAAAAQEBAQEBAQEBAQEBAAAAAAAAAAAAAAAAAAAAAAAAAAABAQEBAQEBAQEBAQEAAAAAAAAAAAAAAAAAAAAAAAAAAAEBAQEBAQEBAQEBAQAAAAAAAAAAAAAAAAAAAAAAAAAAAQEBAQEBAQEBAQEBAAAAAAAAAAAAAAAAAAAAAAAAAAABAQEBAQEBAQEBAQEAAAAAAAAAAAAAAAAAAAAAAAAAAAEBAQEBAQEBAQEBAQAAAAAAAAAAAAAAAAAAAAAAAAAAAQEBAQEBAQEBAQEBAAAAAAAAAAAAAAAAAAAAAAAAAAABAQEBAQEBAQEBAQEAAAAAAAAAAAAAAAAAAAAAAAAAAAEBAQEBAQEBAQEBAQAAAAAAAAAAAAAAAAAAAQEBAQEBAQEBAQEBAQEBAQEBAAAAAAAAAAAAAAAAAAABAQEBAQEBAQEBAQEBAQEBAQEAAAAAAAAAAAAAAAAAAAEBAQEBAQEBAQEBAQEBAQEBAQAAAAAAAAAAAAAAAAAAAQEBAQEBAQEBAQEBAAAAAAAAAAAAAAAAAAAAAAAAAAABAQEBAQEBAQEBAQEAAAAAAAAAAAAAAAAAAAAAAAAAAAEBAQEBAQEBAQEBAQAAAAAAAAAAAAAAAAAAAQEBAQEBAQEBAQEBAQEBAQEBAAAAAAAAAAAAAAAAAAABAQEBAQEBAQEBAQEBAQEBAQEAAAAAAAAAAAAAAAAAAAEBAQEBAQEBAQEBAQEBAQEBAQAAAAAAAAAAAAAAAAAAAQEBAQEBAQEBAQEBAQEBAQEBAAAAAAAAAAAAAAAAAAABAQEBAQEBAQEBAQEBAQEBAQEAAAAAAAAAAAAAAAAAAAEBAQEBAQEBAQEBAQ==" - }, - "palette" : { - "originalArgb8888" : [ -265674 ], - "convertedRgb565" : [ -122 ] } }, "diagnostics" : [ ] @@ -1158,14 +1158,14 @@ "last_modified" : 1774359772489, "fingerprint" : "eeb7cc665386299403b7be1c272375d5077f3647c587f8033aa8c9275f840562", "metadata" : { + "palette" : { + "originalArgb8888" : [ -265674 ], + "convertedRgb565" : [ -122 ] + }, "tile" : { "width" : 32, "height" : 32, "paletteIndices" : "AQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAAAAAAAAAAABAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEAAAAAAAAAAAEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQAAAAAAAAAAAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAAAAAAAAAAABAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEAAAAAAAAAAAEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQAAAAAAAAAAAQEBAQEBAQEBAQEBAAAAAAAAAAAAAAAAAAAAAAAAAAABAQEBAQEBAQEBAQEAAAAAAAAAAAAAAAAAAAAAAAAAAAEBAQEBAQEBAQEBAQAAAAAAAAAAAAAAAAAAAAAAAAAAAQEBAQEBAQEBAQEBAAAAAAAAAAAAAAAAAAAAAAAAAAABAQEBAQEBAQEBAQEAAAAAAAAAAAAAAAAAAAAAAAAAAAEBAQEBAQEBAQEBAQAAAAAAAAAAAAAAAAAAAAAAAAAAAQEBAQEBAQEBAQEBAAAAAAAAAAAAAAAAAAAAAAAAAAABAQEBAQEBAQEBAQEAAAAAAAAAAAAAAAAAAAAAAAAAAAEBAQEBAQEBAQEBAQAAAAAAAAAAAAAAAAAAAQEBAQEBAQEBAQEBAQEBAQEBAAAAAAAAAAAAAAAAAAABAQEBAQEBAQEBAQEBAQEBAQEAAAAAAAAAAAAAAAAAAAEBAQEBAQEBAQEBAQEBAQEBAQAAAAAAAAAAAAAAAAAAAQEBAQEBAQEBAQEBAAAAAAAAAAAAAAAAAAAAAAAAAAABAQEBAQEBAQEBAQEAAAAAAAAAAAAAAAAAAAAAAAAAAAEBAQEBAQEBAQEBAQAAAAAAAAAAAAAAAAAAAQEBAQEBAQEBAQEBAQEBAQEBAAAAAAAAAAAAAAAAAAABAQEBAQEBAQEBAQEBAQEBAQEAAAAAAAAAAAAAAAAAAAEBAQEBAQEBAQEBAQEBAQEBAQAAAAAAAAAAAAAAAAAAAQEBAQEBAQEBAQEBAQEBAQEBAAAAAAAAAAAAAAAAAAABAQEBAQEBAQEBAQEBAQEBAQEAAAAAAAAAAAAAAAAAAAEBAQEBAQEBAQEBAQ==" - }, - "palette" : { - "originalArgb8888" : [ -265674 ], - "convertedRgb565" : [ -122 ] } }, "diagnostics" : [ ] @@ -1176,14 +1176,14 @@ "last_modified" : 1774359772491, "fingerprint" : "eeb7cc665386299403b7be1c272375d5077f3647c587f8033aa8c9275f840562", "metadata" : { + "palette" : { + "originalArgb8888" : [ -265674 ], + "convertedRgb565" : [ -122 ] + }, "tile" : { "width" : 32, "height" : 32, "paletteIndices" : "AQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAAAAAAAAAAABAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEAAAAAAAAAAAEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQAAAAAAAAAAAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAAAAAAAAAAABAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEAAAAAAAAAAAEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQAAAAAAAAAAAQEBAQEBAQEBAQEBAAAAAAAAAAAAAAAAAAAAAAAAAAABAQEBAQEBAQEBAQEAAAAAAAAAAAAAAAAAAAAAAAAAAAEBAQEBAQEBAQEBAQAAAAAAAAAAAAAAAAAAAAAAAAAAAQEBAQEBAQEBAQEBAAAAAAAAAAAAAAAAAAAAAAAAAAABAQEBAQEBAQEBAQEAAAAAAAAAAAAAAAAAAAAAAAAAAAEBAQEBAQEBAQEBAQAAAAAAAAAAAAAAAAAAAAAAAAAAAQEBAQEBAQEBAQEBAAAAAAAAAAAAAAAAAAAAAAAAAAABAQEBAQEBAQEBAQEAAAAAAAAAAAAAAAAAAAAAAAAAAAEBAQEBAQEBAQEBAQAAAAAAAAAAAAAAAAAAAQEBAQEBAQEBAQEBAQEBAQEBAAAAAAAAAAAAAAAAAAABAQEBAQEBAQEBAQEBAQEBAQEAAAAAAAAAAAAAAAAAAAEBAQEBAQEBAQEBAQEBAQEBAQAAAAAAAAAAAAAAAAAAAQEBAQEBAQEBAQEBAAAAAAAAAAAAAAAAAAAAAAAAAAABAQEBAQEBAQEBAQEAAAAAAAAAAAAAAAAAAAAAAAAAAAEBAQEBAQEBAQEBAQAAAAAAAAAAAAAAAAAAAQEBAQEBAQEBAQEBAQEBAQEBAAAAAAAAAAAAAAAAAAABAQEBAQEBAQEBAQEBAQEBAQEAAAAAAAAAAAAAAAAAAAEBAQEBAQEBAQEBAQEBAQEBAQAAAAAAAAAAAAAAAAAAAQEBAQEBAQEBAQEBAQEBAQEBAAAAAAAAAAAAAAAAAAABAQEBAQEBAQEBAQEBAQEBAQEAAAAAAAAAAAAAAAAAAAEBAQEBAQEBAQEBAQ==" - }, - "palette" : { - "originalArgb8888" : [ -265674 ], - "convertedRgb565" : [ -122 ] } }, "diagnostics" : [ ] @@ -1194,14 +1194,14 @@ "last_modified" : 1774359772492, "fingerprint" : "eeb7cc665386299403b7be1c272375d5077f3647c587f8033aa8c9275f840562", "metadata" : { + "palette" : { + "originalArgb8888" : [ -265674 ], + "convertedRgb565" : [ -122 ] + }, "tile" : { "width" : 32, "height" : 32, "paletteIndices" : "AQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAAAAAAAAAAABAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEAAAAAAAAAAAEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQAAAAAAAAAAAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAAAAAAAAAAABAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEAAAAAAAAAAAEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQAAAAAAAAAAAQEBAQEBAQEBAQEBAAAAAAAAAAAAAAAAAAAAAAAAAAABAQEBAQEBAQEBAQEAAAAAAAAAAAAAAAAAAAAAAAAAAAEBAQEBAQEBAQEBAQAAAAAAAAAAAAAAAAAAAAAAAAAAAQEBAQEBAQEBAQEBAAAAAAAAAAAAAAAAAAAAAAAAAAABAQEBAQEBAQEBAQEAAAAAAAAAAAAAAAAAAAAAAAAAAAEBAQEBAQEBAQEBAQAAAAAAAAAAAAAAAAAAAAAAAAAAAQEBAQEBAQEBAQEBAAAAAAAAAAAAAAAAAAAAAAAAAAABAQEBAQEBAQEBAQEAAAAAAAAAAAAAAAAAAAAAAAAAAAEBAQEBAQEBAQEBAQAAAAAAAAAAAAAAAAAAAQEBAQEBAQEBAQEBAQEBAQEBAAAAAAAAAAAAAAAAAAABAQEBAQEBAQEBAQEBAQEBAQEAAAAAAAAAAAAAAAAAAAEBAQEBAQEBAQEBAQEBAQEBAQAAAAAAAAAAAAAAAAAAAQEBAQEBAQEBAQEBAAAAAAAAAAAAAAAAAAAAAAAAAAABAQEBAQEBAQEBAQEAAAAAAAAAAAAAAAAAAAAAAAAAAAEBAQEBAQEBAQEBAQAAAAAAAAAAAAAAAAAAAQEBAQEBAQEBAQEBAQEBAQEBAAAAAAAAAAAAAAAAAAABAQEBAQEBAQEBAQEBAQEBAQEAAAAAAAAAAAAAAAAAAAEBAQEBAQEBAQEBAQEBAQEBAQAAAAAAAAAAAAAAAAAAAQEBAQEBAQEBAQEBAQEBAQEBAAAAAAAAAAAAAAAAAAABAQEBAQEBAQEBAQEBAQEBAQEAAAAAAAAAAAAAAAAAAAEBAQEBAQEBAQEBAQ==" - }, - "palette" : { - "originalArgb8888" : [ -265674 ], - "convertedRgb565" : [ -122 ] } }, "diagnostics" : [ ] @@ -1212,14 +1212,14 @@ "last_modified" : 1774359772493, "fingerprint" : "eeb7cc665386299403b7be1c272375d5077f3647c587f8033aa8c9275f840562", "metadata" : { + "palette" : { + "originalArgb8888" : [ -265674 ], + "convertedRgb565" : [ -122 ] + }, "tile" : { "width" : 32, "height" : 32, "paletteIndices" : "AQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAAAAAAAAAAABAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEAAAAAAAAAAAEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQAAAAAAAAAAAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAAAAAAAAAAABAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEAAAAAAAAAAAEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQAAAAAAAAAAAQEBAQEBAQEBAQEBAAAAAAAAAAAAAAAAAAAAAAAAAAABAQEBAQEBAQEBAQEAAAAAAAAAAAAAAAAAAAAAAAAAAAEBAQEBAQEBAQEBAQAAAAAAAAAAAAAAAAAAAAAAAAAAAQEBAQEBAQEBAQEBAAAAAAAAAAAAAAAAAAAAAAAAAAABAQEBAQEBAQEBAQEAAAAAAAAAAAAAAAAAAAAAAAAAAAEBAQEBAQEBAQEBAQAAAAAAAAAAAAAAAAAAAAAAAAAAAQEBAQEBAQEBAQEBAAAAAAAAAAAAAAAAAAAAAAAAAAABAQEBAQEBAQEBAQEAAAAAAAAAAAAAAAAAAAAAAAAAAAEBAQEBAQEBAQEBAQAAAAAAAAAAAAAAAAAAAQEBAQEBAQEBAQEBAQEBAQEBAAAAAAAAAAAAAAAAAAABAQEBAQEBAQEBAQEBAQEBAQEAAAAAAAAAAAAAAAAAAAEBAQEBAQEBAQEBAQEBAQEBAQAAAAAAAAAAAAAAAAAAAQEBAQEBAQEBAQEBAAAAAAAAAAAAAAAAAAAAAAAAAAABAQEBAQEBAQEBAQEAAAAAAAAAAAAAAAAAAAAAAAAAAAEBAQEBAQEBAQEBAQAAAAAAAAAAAAAAAAAAAQEBAQEBAQEBAQEBAQEBAQEBAAAAAAAAAAAAAAAAAAABAQEBAQEBAQEBAQEBAQEBAQEAAAAAAAAAAAAAAAAAAAEBAQEBAQEBAQEBAQEBAQEBAQAAAAAAAAAAAAAAAAAAAQEBAQEBAQEBAQEBAQEBAQEBAAAAAAAAAAAAAAAAAAABAQEBAQEBAQEBAQEBAQEBAQEAAAAAAAAAAAAAAAAAAAEBAQEBAQEBAQEBAQ==" - }, - "palette" : { - "originalArgb8888" : [ -265674 ], - "convertedRgb565" : [ -122 ] } }, "diagnostics" : [ ] @@ -1230,14 +1230,14 @@ "last_modified" : 1774359772494, "fingerprint" : "eeb7cc665386299403b7be1c272375d5077f3647c587f8033aa8c9275f840562", "metadata" : { + "palette" : { + "originalArgb8888" : [ -265674 ], + "convertedRgb565" : [ -122 ] + }, "tile" : { "width" : 32, "height" : 32, "paletteIndices" : "AQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAAAAAAAAAAABAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEAAAAAAAAAAAEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQAAAAAAAAAAAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAAAAAAAAAAABAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEAAAAAAAAAAAEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQAAAAAAAAAAAQEBAQEBAQEBAQEBAAAAAAAAAAAAAAAAAAAAAAAAAAABAQEBAQEBAQEBAQEAAAAAAAAAAAAAAAAAAAAAAAAAAAEBAQEBAQEBAQEBAQAAAAAAAAAAAAAAAAAAAAAAAAAAAQEBAQEBAQEBAQEBAAAAAAAAAAAAAAAAAAAAAAAAAAABAQEBAQEBAQEBAQEAAAAAAAAAAAAAAAAAAAAAAAAAAAEBAQEBAQEBAQEBAQAAAAAAAAAAAAAAAAAAAAAAAAAAAQEBAQEBAQEBAQEBAAAAAAAAAAAAAAAAAAAAAAAAAAABAQEBAQEBAQEBAQEAAAAAAAAAAAAAAAAAAAAAAAAAAAEBAQEBAQEBAQEBAQAAAAAAAAAAAAAAAAAAAQEBAQEBAQEBAQEBAQEBAQEBAAAAAAAAAAAAAAAAAAABAQEBAQEBAQEBAQEBAQEBAQEAAAAAAAAAAAAAAAAAAAEBAQEBAQEBAQEBAQEBAQEBAQAAAAAAAAAAAAAAAAAAAQEBAQEBAQEBAQEBAAAAAAAAAAAAAAAAAAAAAAAAAAABAQEBAQEBAQEBAQEAAAAAAAAAAAAAAAAAAAAAAAAAAAEBAQEBAQEBAQEBAQAAAAAAAAAAAAAAAAAAAQEBAQEBAQEBAQEBAQEBAQEBAAAAAAAAAAAAAAAAAAABAQEBAQEBAQEBAQEBAQEBAQEAAAAAAAAAAAAAAAAAAAEBAQEBAQEBAQEBAQEBAQEBAQAAAAAAAAAAAAAAAAAAAQEBAQEBAQEBAQEBAQEBAQEBAAAAAAAAAAAAAAAAAAABAQEBAQEBAQEBAQEBAQEBAQEAAAAAAAAAAAAAAAAAAAEBAQEBAQEBAQEBAQ==" - }, - "palette" : { - "originalArgb8888" : [ -265674 ], - "convertedRgb565" : [ -122 ] } }, "diagnostics" : [ ] @@ -1248,14 +1248,14 @@ "last_modified" : 1774359772495, "fingerprint" : "eeb7cc665386299403b7be1c272375d5077f3647c587f8033aa8c9275f840562", "metadata" : { + "palette" : { + "originalArgb8888" : [ -265674 ], + "convertedRgb565" : [ -122 ] + }, "tile" : { "width" : 32, "height" : 32, "paletteIndices" : "AQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAAAAAAAAAAABAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEAAAAAAAAAAAEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQAAAAAAAAAAAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAAAAAAAAAAABAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEAAAAAAAAAAAEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQAAAAAAAAAAAQEBAQEBAQEBAQEBAAAAAAAAAAAAAAAAAAAAAAAAAAABAQEBAQEBAQEBAQEAAAAAAAAAAAAAAAAAAAAAAAAAAAEBAQEBAQEBAQEBAQAAAAAAAAAAAAAAAAAAAAAAAAAAAQEBAQEBAQEBAQEBAAAAAAAAAAAAAAAAAAAAAAAAAAABAQEBAQEBAQEBAQEAAAAAAAAAAAAAAAAAAAAAAAAAAAEBAQEBAQEBAQEBAQAAAAAAAAAAAAAAAAAAAAAAAAAAAQEBAQEBAQEBAQEBAAAAAAAAAAAAAAAAAAAAAAAAAAABAQEBAQEBAQEBAQEAAAAAAAAAAAAAAAAAAAAAAAAAAAEBAQEBAQEBAQEBAQAAAAAAAAAAAAAAAAAAAQEBAQEBAQEBAQEBAQEBAQEBAAAAAAAAAAAAAAAAAAABAQEBAQEBAQEBAQEBAQEBAQEAAAAAAAAAAAAAAAAAAAEBAQEBAQEBAQEBAQEBAQEBAQAAAAAAAAAAAAAAAAAAAQEBAQEBAQEBAQEBAAAAAAAAAAAAAAAAAAAAAAAAAAABAQEBAQEBAQEBAQEAAAAAAAAAAAAAAAAAAAAAAAAAAAEBAQEBAQEBAQEBAQAAAAAAAAAAAAAAAAAAAQEBAQEBAQEBAQEBAQEBAQEBAAAAAAAAAAAAAAAAAAABAQEBAQEBAQEBAQEBAQEBAQEAAAAAAAAAAAAAAAAAAAEBAQEBAQEBAQEBAQEBAQEBAQAAAAAAAAAAAAAAAAAAAQEBAQEBAQEBAQEBAQEBAQEBAAAAAAAAAAAAAAAAAAABAQEBAQEBAQEBAQEBAQEBAQEAAAAAAAAAAAAAAAAAAAEBAQEBAQEBAQEBAQ==" - }, - "palette" : { - "originalArgb8888" : [ -265674 ], - "convertedRgb565" : [ -122 ] } }, "diagnostics" : [ ] @@ -1266,14 +1266,14 @@ "last_modified" : 1775797786950, "fingerprint" : "0526996900bdeef23c72fe987fb45800f11895946dcd5f0f7f8390c879069a37", "metadata" : { + "palette" : { + "originalArgb8888" : [ -265674, -1736296, -13905598, -11518505, -14439577, -2467509 ], + "convertedRgb565" : [ -122, -7149, 11912, 20986, 9548, -9527 ] + }, "tile" : { "width" : 32, "height" : 32, "paletteIndices" : "AQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQECAgIBAQEBAQEBAQEBAQEBAQEBAwMDAwMDAQEBAQEBAgICAgICAgIBAQEBAQEBAQEBAQMDAwMDAwMBAQEBAQICAgICAgICAQEBAQEBAQEBAQEBAQMDAwMDAQEBAQEBAgICAgICAgEBAQEBAQQEBAQBAQEBAQEBAQEBAQEBAQEBAgICAgIBAQEBAQEEBAQEBAQBAQEBAQEBAQEBAQEBAQEBAgECAQEBAQEBAQQEBAQEAQEBAQEBAAAAAAAAAAABAQECAQEBAQEBAQEEBAQEBAEBAQEBAQEAAAAAAAAAAAEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQAAAAAAAAAAAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAAAAAAAAAAABAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEAAAAAAAAAAAEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQAAAAAAAAAAAQEBAQEBAQEBAQEBAAAAAAAAAAAAAAAAAAAAAAAAAAABAQEBAQEBAQEBAQEAAAAAAAAAAAAAAAAAAAAAAAAAAAEBAQEBAQEBAQEBAQAAAAAAAAAAAAAAAAAAAAAAAAAAAQEBAQEBAQUBAQEBAAAAAAAAAAAAAAAAAAAAAAAAAAABAQEBAQUFBQEBAQEAAAAAAAAAAAAAAAAAAAAAAAAAAAEBAQEFBQUFBQEBAQAAAAAAAAAAAAAAAAAAAAAAAAAAAQEBBQUFBQUBAQEBAAAAAAAAAAAAAAAAAAAAAAAAAAABAQEBBQUFAQEBAQEAAAAAAAAAAAAAAAAAAAAAAAAAAAEBAQEBAQEBAQEBAQAAAAAAAAAAAAAAAAAAAQEBAQEBAQEBAQEBAQEBAQEBAAAAAAAAAAAAAAAAAAABAQEBAQEBAQEBAQEBAQEBAQEAAAAAAAAAAAAAAAAAAAEBAQEBAQYGBgYBAQEBAQEBAQAAAAAAAAAAAAAAAAAAAQEBAQEBBgYGBgEBAAAAAAAAAAAAAAAAAAAAAAAAAAABAQEBAQEGBgYGAQEAAAAAAAAAAAAAAAAAAAAAAAAAAAEBAQEBAQYGBgYBAQAAAAAAAAAAAAAAAAAAAQEBAQEBAQEBAQEBAQYGAQEBAAAAAAAAAAAAAAAAAAABAQEBAQEBAQEBAQEBAQEBAQEAAAAAAAAAAAAAAAAAAAEBAQEBAQEBAQEBAQEBAQEBAQAAAAAAAAAAAAAAAAAAAQEBAQEBAQEBAQEBAQEBAQEBAAAAAAAAAAAAAAAAAAABAQEBAQEBAQEBAQEBAQEBAQEAAAAAAAAAAAAAAAAAAAEBAQEBAQEBAQEBAQ==" - }, - "palette" : { - "originalArgb8888" : [ -265674, -1736296, -13905598, -11518505, -14439577, -2467509 ], - "convertedRgb565" : [ -122, -7149, 11912, 20986, 9548, -9527 ] } }, "diagnostics" : [ ] @@ -1314,14 +1314,14 @@ "last_modified" : 1775797786770, "fingerprint" : "aa7d241deabcebe29a6096e14eaf16fdc06cf06380c11a507620b00fc7bff094", "metadata" : { + "palette" : { + "originalArgb8888" : [ -265674 ], + "convertedRgb565" : [ -122 ] + }, "tile" : { "width" : 16, "height" : 16, "paletteIndices" : "AQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAAAAAAEBAQEBAQEBAQEBAQAAAAABAQEBAQEBAQEBAQEAAAAAAQEBAQEBAAAAAAAAAAAAAAEBAQEBAQAAAAAAAAAAAAABAQEBAQEAAAAAAAAAAAAAAQEBAQEBAAAAAAAAAAAAAAEBAQEBAQAAAAAAAAABAQEBAQEBAQEAAAAAAAAAAQEBAQEBAAAAAAAAAAAAAAEBAQEBAQAAAAAAAAABAQEBAQEBAQEAAAAAAAAAAQEBAQEBAQEBAAAAAAAAAAEBAQEBAQ==" - }, - "palette" : { - "originalArgb8888" : [ -265674 ], - "convertedRgb565" : [ -122 ] } }, "diagnostics" : [ ] @@ -1344,14 +1344,14 @@ "last_modified" : 1775797786709, "fingerprint" : "6ca635a7906067b6a2a8460a8562718c445783e6df18b9f2c80c83c5ac569db6", "metadata" : { + "palette" : { + "originalArgb8888" : [ -130562, -14145496, -2043712, -460560, -13082456, -6252424, -10977088 ], + "convertedRgb565" : [ -2017, 10565, -6504, -34, 15125, -23345, 23576 ] + }, "tile" : { "width" : 32, "height" : 32, "paletteIndices" : "AQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQICAgICAgICAgAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAICAwMDAwMDAgAAAAAAAAAAAAACAgIAAAAAAAAAAAAAAAIEBQUFBQUDAgAAAAAAAgICAgMDAwIAAAAAAAAAAAAAAgQFAwYGBgUDAgICAgIDAwMDBQUFAwIAAAAAAAAAAAACBAUDBgYGBgUEBAQEAwUFBQUGAwMFBAICAAAAAAAAAAIEBQMGBgYGAwUFBwcFBgYGBgMDAwMFBAQCAgAAAAAAAgQFAwYGBgMDAwQEBAMGBgYGBgMDAwMHBwQDAgAAAAACBAUDBgYGAwMDAwQEAwYGBgYGAwMDBAQEBQUDAgIAAAIEBQMGBgYDAwMDBAQDBgYGBgYDAwMDBAQDAwUGAgAAAgQFAwYGBgMDAwMEBAMGBgYGBQUFBQUEBAUFBgIAAAACBAUDBgYGAwMDAwQEAwYGBQUGAwMDAwcHAwYCAAAAAAIEBQMFBQUFBQMDBAQDBgUGBgICAgICBAQCAgAAAAAAAgQFBQYGBgYDBQMEBAMFBgICAAAAAAACAgAAAAAAAAACBAMDBgICAgIDBQcHBQYCAAAAAAAAAAAAAAAAAAAAAgIDAwMCAAAAAAIEBAMDAgAAAAAAAAAAAAAAAAAAAAICAgICAgAAAAAAAAICAgIAAAAAAAAAAAAAAAAAAAAAAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQ==" - }, - "palette" : { - "originalArgb8888" : [ -130562, -14145496, -2043712, -460560, -13082456, -6252424, -10977088 ], - "convertedRgb565" : [ -2017, 10565, -6504, -34, 15125, -23345, 23576 ] } }, "diagnostics" : [ { @@ -1396,14 +1396,14 @@ "last_modified" : 1775797786706, "fingerprint" : "7feab8c868bb446afd3dd7250e70504fb0ca228f463650d2dd7c525144e0b321", "metadata" : { + "palette" : { + "originalArgb8888" : [ -16777216, -2109505, -526353, -395279, -130562, -13082456, -10911807, -6318217, -6186631, -6187143, -6318215, -13148249, -13016663, -14080215 ], + "convertedRgb565" : [ 0, -8585, -2115, -66, -2017, 15125, 23544, -25426, -23345, -23377, -25425, 13044, 15125, 10533 ] + }, "tile" : { "width" : 32, "height" : 32, "paletteIndices" : "AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAEBAQEBAQEAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAEBAgMDBAEBAQEBBQUFAAUFBQUFBQUBAQAAAAAAAAAAAAECBgcHBAIICAkBBQUFBQUFBQEBAQICAQEAAAAFBQAAAQIGAwMHBgYGBgIBBQUFBQEBCgIIBgYDBAEBBQUFAAABAgYDAwIJCQsJBgIBAQEBCAgMDA0JAgcHAwMBBQUAAAECBgMDAgsLCwsLBgMDAwIGBgkCCwILAgIHAwEFBQAAAQIGAwMCCQkJCQkCBgcHBgsLCwsCCwICAwMHAwEFAAABAgYDAgkJCQkJCQICAwMCCQkJAgkGBgYHBwcDDgUAAAECBwMCCQkJCQkJAgIDAgkJCQkGBgsCAwMDAwQEAQAAAQIHAwIJCQkJCQkCAgMCCQkJBgkLAQEBAQEBAQQBAAABAgcDAgkJCQkJAgICAwILCQYJAQEFBQUFBQUFAQEAAAECBwMCCQkJCQYGAgIDAgkGCwEFBQUFBQUFBQAAAAAAAQIHAwIJCQYGCQIGBgcMBgkBBQUFBQUFBQAAAAAAAAABAgcGBgYGCQsBAQIDBAIKAQUFBQUFBQAAAAAAAAAAAQECAwIJCQkBAQAAAQEBAQEAAAAAAAAAAAAAAAAAAAEBAQEBAQEBAQAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA==" - }, - "palette" : { - "originalArgb8888" : [ -16777216, -2109505, -526353, -395279, -130562, -13082456, -10911807, -6318217, -6186631, -6187143, -6318215, -13148249, -13016663, -14080215 ], - "convertedRgb565" : [ 0, -8585, -2115, -66, -2017, 15125, 23544, -25426, -23345, -23377, -25425, 13044, 15125, 10533 ] } }, "diagnostics" : [ ] @@ -1414,14 +1414,14 @@ "last_modified" : 1775797786710, "fingerprint" : "c363f3ef7f32d9b249c7dc8babdb3eb5aae68c524099e5e97290202b054dda71", "metadata" : { + "palette" : { + "originalArgb8888" : [ -14671840, -11431408, -9326048, -802016, -3964416, -5086944, -789517, -810399, -1863087, -10403552, -5078447 ], + "convertedRgb565" : [ 8452, 21634, 30084, -2556, -15360, -19708, -2146, -2804, -7030, 25092, -19446 ] + }, "tile" : { "width" : 32, "height" : 32, "paletteIndices" : "AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAABAQEBAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAEBAQICAwMBAQAAAAAAAAAAAAAAAAAAAAAAAAAAAAABBAQBAgIDAwMCAQAAAAAAAAAAAAAAAAAAAAAAAAAAAQUFBAQBAgIDAgICAQAAAAAAAAAAAAAAAAAAAAAAAAABBQEFBAUBAgICAgMBAAAAAAAAAAAAAAAAAAAAAAAAAAABBgEFBQUBAgECAgMBAAAAAAAAAAAAAAAAAAAAAAAAAAEGBwEFBAEBCAECAwEAAAAAAAAAAAAAAAAAAAAAAAAAAQgBBwEEAQgJAQICAQAAAAAAAAAAAAAAAAAAAAAAAAEICAEHAQQBCQYBAgIBAAAAAAAAAAAAAAAAAAAAAAAAAAEGCQkBBQEGAQUBAgEAAAAAAAAAAAAAAAAAAAAAAAAAAAEBBgYBBgEBAQABAAAAAAAAAAAAAAAAAAAAAAAAAAAAAQcBAQEBAgIBAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAECAwECAwIBAgEAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAQECAQcHBwECAQAAAAAAAAAAAAAAAAAAAAAAAAAAAAABBAEBAQEBAQECAQAAAAAAAAAAAAAAAAAAAAAAAAAAAAABAgEJCgoBAgEAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAQEBAQEJCQEBAQAAAAAAAAAAAAAAAAAAAAAAAAAAAAEBAQEKAQEBAQEBAQAAAAAAAAAAAAAAAAAAAAAAAAAAAQEBAQELCwoKAQEBAAAAAAAAAAAAAAAAAAAAAAAAAAAAAQEBAQEBAQEBAQAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAEBAQEBAQAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA==" - }, - "palette" : { - "originalArgb8888" : [ -14671840, -11431408, -9326048, -802016, -3964416, -5086944, -789517, -810399, -1863087, -10403552, -5078447 ], - "convertedRgb565" : [ 8452, 21634, 30084, -2556, -15360, -19708, -2146, -2804, -7030, 25092, -19446 ] } }, "diagnostics" : [ ] @@ -1432,14 +1432,14 @@ "last_modified" : 1775797786711, "fingerprint" : "e2130efbb9643b41a4fb62619f2713402f9622c7db040fe18d929609ef70b89a", "metadata" : { + "palette" : { + "originalArgb8888" : [ -14671840, -11431408, -9326048, -802016, -3964416, -5086944, -789517, -810399, -1863087, -10403552, -5078447 ], + "convertedRgb565" : [ 8452, 21634, 30084, -2556, -15360, -19708, -2146, -2804, -7030, 25092, -19446 ] + }, "tile" : { "width" : 32, "height" : 32, "paletteIndices" : "AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAQEBAQAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAABAQECAgMDAQEAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAQQEAQICAwMDAgEAAAAAAAAAAAAAAAAAAAAAAAAAAAEFBQQEAQICAwICAgEAAAAAAAAAAAAAAAAAAAAAAAAAAQUBBQQFAQICAgIDAQAAAAAAAAAAAAAAAAAAAAAAAAAAAQYBBQUFAQIBAgIDAQAAAAAAAAAAAAAAAAAAAAAAAAABBgcBBQQBAQgBAgMBAAAAAAAAAAAAAAAAAAAAAAAAAAEIAQcBBAEICQECAgEAAAAAAAAAAAAAAAAAAAAAAAABCAgBBwEEAQkGAQICAQAAAAAAAAAAAAAAAAAAAAAAAAABBgkJAQUBBgEFAQIBAAAAAAAAAAAAAAAAAAAAAAAAAAABAQYGAQYBAQEAAQAAAAAAAAAAAAAAAAAAAAAAAAAAAAEHAQEBAQECAQAAAAAAAAAAAAAAAAAAAAAAAAAAAAABAgEBBwMBAwMBAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAEBCQoBBwEDAgEBAAAAAAAAAAAAAAAAAAAAAAAAAAABAgEJCQoBAgIBAQIBAAAAAAAAAAAAAAAAAAAAAAAAAAECAgEBAQICAQECAQEAAAAAAAAAAAAAAAAAAAAAAAAAAAEBAgECAQECAgEBAQAAAAAAAAAAAAAAAAAAAAAAAAAAAQEBAQICAgEBAQoKAQAAAAAAAAAAAAAAAAAAAAAAAAEBAQEBAQEBAQELCwoBAAAAAAAAAAAAAAAAAAAAAAAAAQEBAQEBAQEBAQsLAQEAAAAAAAAAAAAAAAAAAAAAAAAAAQEBAQEBAQEBAQEBAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAEBAQEBAQAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA==" - }, - "palette" : { - "originalArgb8888" : [ -14671840, -11431408, -9326048, -802016, -3964416, -5086944, -789517, -810399, -1863087, -10403552, -5078447 ], - "convertedRgb565" : [ 8452, 21634, 30084, -2556, -15360, -19708, -2146, -2804, -7030, 25092, -19446 ] } }, "diagnostics" : [ ] @@ -1450,14 +1450,14 @@ "last_modified" : 1775797786713, "fingerprint" : "9216dfc6a6226fac398e9f781550d23fbfaa65bd377cdda69187149beca114ec", "metadata" : { + "palette" : { + "originalArgb8888" : [ -14671840, -11431408, -9326048, -802016, -3964416, -5086944, -789517, -810399, -1863087, -10403552, -5078447 ], + "convertedRgb565" : [ 8452, 21634, 30084, -2556, -15360, -19708, -2146, -2804, -7030, 25092, -19446 ] + }, "tile" : { "width" : 32, "height" : 32, "paletteIndices" : "AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAQEBAQAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAEBAQECAgMDAQEAAAEBAAAAAAAAAAAAAAAAAAAAAAABBAQEAQICAwMDAgEBAwEAAAAAAAAAAAAAAAAAAAAAAAEFBQQEAQICAwICAQIDAQAAAAAAAAAAAAAAAAAAAAAAAAEBBQQFAQICAgICAwEBAAAAAAAAAAAAAAAAAAAAAAAAAQYBBQUFAQIBAgICAQAAAAAAAAAAAAAAAAAAAAAAAAABBgcBBQQFAQgBAQEBAAAAAAAAAAAAAAAAAAAAAAAAAAEIAQcBBAUBCQEBBQUBAAAAAAAAAAAAAAAAAAAAAAABCAgBBwgBBAUBAQUBAAAAAAAAAAAAAAAAAAAAAAAAAAABBgkJBgYBAQEBAQAAAAAAAAAAAAAAAAAAAAAAAAAAAAABAQYGBgYBAQAAAAAAAAAAAAAAAAAAAAAAAAAAAAABAQEBAQEBAQMBAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAEJCgEHAwECAwEBAQAAAAAAAAAAAAAAAAAAAAAAAAABAQkKAQcCAQIDAQEBAQAAAAAAAAAAAAAAAAAAAAAAAAEKAQEBAQECAgEBAgELAQAAAAAAAAAAAAAAAAAAAAAAAQEKAQICAQEBAgIBAQoLAQAAAAAAAAAAAAAAAAAAAAAAAQEBAQECAgICAQEAAQEAAAAAAAAAAAAAAAAAAAAAAAAAAQEBAQEBAQEBAQAAAAAAAAAAAAAAAAAAAAAAAAAAAAEBAQEBAQEBAQEBAQAAAAAAAAAAAAAAAAAAAAAAAAAAAQEBAQEBAQEBAQEBAAAAAAAAAAAAAAAAAAAAAAAAAAAAAQEBAQEBAQEBAQAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAEBAQEBAQAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA==" - }, - "palette" : { - "originalArgb8888" : [ -14671840, -11431408, -9326048, -802016, -3964416, -5086944, -789517, -810399, -1863087, -10403552, -5078447 ], - "convertedRgb565" : [ 8452, 21634, 30084, -2556, -15360, -19708, -2146, -2804, -7030, 25092, -19446 ] } }, "diagnostics" : [ ] @@ -1468,14 +1468,14 @@ "last_modified" : 1775797786712, "fingerprint" : "ebc4b7ca7bb1455288681c5d71424f60f658a44cb343d0c3934329cec676c867", "metadata" : { + "palette" : { + "originalArgb8888" : [ -14671840, -11431408, -9326048, -802016, -3964416, -5086944, -789517, -810399, -1863087, -10403552, -5078447 ], + "convertedRgb565" : [ 8452, 21634, 30084, -2556, -15360, -19708, -2146, -2804, -7030, 25092, -19446 ] + }, "tile" : { "width" : 32, "height" : 32, "paletteIndices" : "AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAABAQEBAAAAAAEBAAAAAAAAAAAAAAAAAAAAAAAAAAEBAQICAwMBAQEBAwEAAAAAAAAAAAAAAAAAAAAAAAABBAQBAgIDAwMCAQMDAQAAAAAAAAAAAAAAAAAAAAAAAQUFBAQBAgIDAgICAwIBAAAAAAAAAAAAAAAAAAAAAAABBQEFBAUBAgICAgMCAQAAAAAAAAAAAAAAAAAAAAAAAAABBgEFBQUBAgECAgIBAAAAAAAAAAAAAAAAAAAAAAAAAAEGBwEFBAUBCAEBAQAAAAAAAAAAAAAAAAAAAAAAAAAAAQgBBwEEBQEJAQEAAAAAAAAAAAAAAAAAAAAAAAAAAAEICAEHCQEEBQEFAQAAAAAAAAAAAAAAAAAAAAAAAAAAAQEBCQkGBgEBAQUBAAAAAAAAAAAAAAAAAAAAAAAAAAABCQoBAQEGBgEBAQUBAAAAAAAAAAAAAAAAAAAAAAAAAAEKCgEHAgEBAQMBAQAAAAAAAAAAAAAAAAAAAAAAAAAAAAEBBwICAQIDAwEBAAAAAAAAAAAAAAAAAAAAAAAAAAABAQEBAQECAgMBAQIBAAAAAAAAAAAAAAAAAAAAAAAAAQoBAQIBAgICAgECAQEAAAAAAAAAAAAAAAAAAAAAAAABCgoBAgIBAQEBAgELAQAAAAAAAAAAAAAAAAAAAAAAAAEBAQEBAQICAgIBAQEAAAAAAAAAAAAAAAAAAAAAAAAAAAEBAQEBAQEBAQEBAQAAAAAAAAAAAAAAAAAAAAAAAAAAAQEBAQEBAQEBAQEBAAAAAAAAAAAAAAAAAAAAAAAAAAAAAQEBAQEBAQEBAQAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAEBAQEBAQAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA==" - }, - "palette" : { - "originalArgb8888" : [ -14671840, -11431408, -9326048, -802016, -3964416, -5086944, -789517, -810399, -1863087, -10403552, -5078447 ], - "convertedRgb565" : [ 8452, 21634, 30084, -2556, -15360, -19708, -2146, -2804, -7030, 25092, -19446 ] } }, "diagnostics" : [ ] @@ -1486,14 +1486,14 @@ "last_modified" : 1775797786718, "fingerprint" : "c363f3ef7f32d9b249c7dc8babdb3eb5aae68c524099e5e97290202b054dda71", "metadata" : { + "palette" : { + "originalArgb8888" : [ -14671840, -11431408, -9326048, -802016, -3964416, -5086944, -789517, -810399, -1863087, -10403552, -5078447 ], + "convertedRgb565" : [ 8452, 21634, 30084, -2556, -15360, -19708, -2146, -2804, -7030, 25092, -19446 ] + }, "tile" : { "width" : 32, "height" : 32, "paletteIndices" : "AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAABAQEBAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAEBAQICAwMBAQAAAAAAAAAAAAAAAAAAAAAAAAAAAAABBAQBAgIDAwMCAQAAAAAAAAAAAAAAAAAAAAAAAAAAAQUFBAQBAgIDAgICAQAAAAAAAAAAAAAAAAAAAAAAAAABBQEFBAUBAgICAgMBAAAAAAAAAAAAAAAAAAAAAAAAAAABBgEFBQUBAgECAgMBAAAAAAAAAAAAAAAAAAAAAAAAAAEGBwEFBAEBCAECAwEAAAAAAAAAAAAAAAAAAAAAAAAAAQgBBwEEAQgJAQICAQAAAAAAAAAAAAAAAAAAAAAAAAEICAEHAQQBCQYBAgIBAAAAAAAAAAAAAAAAAAAAAAAAAAEGCQkBBQEGAQUBAgEAAAAAAAAAAAAAAAAAAAAAAAAAAAEBBgYBBgEBAQABAAAAAAAAAAAAAAAAAAAAAAAAAAAAAQcBAQEBAgIBAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAECAwECAwIBAgEAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAQECAQcHBwECAQAAAAAAAAAAAAAAAAAAAAAAAAAAAAABBAEBAQEBAQECAQAAAAAAAAAAAAAAAAAAAAAAAAAAAAABAgEJCgoBAgEAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAQEBAQEJCQEBAQAAAAAAAAAAAAAAAAAAAAAAAAAAAAEBAQEKAQEBAQEBAQAAAAAAAAAAAAAAAAAAAAAAAAAAAQEBAQELCwoKAQEBAAAAAAAAAAAAAAAAAAAAAAAAAAAAAQEBAQEBAQEBAQAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAEBAQEBAQAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA==" - }, - "palette" : { - "originalArgb8888" : [ -14671840, -11431408, -9326048, -802016, -3964416, -5086944, -789517, -810399, -1863087, -10403552, -5078447 ], - "convertedRgb565" : [ 8452, 21634, 30084, -2556, -15360, -19708, -2146, -2804, -7030, 25092, -19446 ] } }, "diagnostics" : [ ] @@ -1504,14 +1504,14 @@ "last_modified" : 1775797786717, "fingerprint" : "1ba8ce75c445396334737143e0cfa56c87a1fb64cca8ad0962192594849249eb", "metadata" : { + "palette" : { + "originalArgb8888" : [ -14671840, -11431408, -9326048, -802016, -3964416, -5086944, -789517, -810399, -1863087, -10403552 ], + "convertedRgb565" : [ 8452, 21634, 30084, -2556, -15360, -19708, -2146, -2804, -7030, 25092 ] + }, "tile" : { "width" : 32, "height" : 32, "paletteIndices" : "AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAABAQEBAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAEBAQICAwMBAQAAAAAAAAAAAAAAAAAAAAAAAAAAAAABBAQBAgIDAwMCAQAAAAAAAAAAAAAAAAAAAAAAAAAAAQUFBAQBAgIDAgICAQAAAAAAAAAAAAAAAAAAAAAAAAABBQEFBAUBAgICAgMBAAAAAAAAAAAAAAAAAAAAAAAAAAABBgEFBQUBAgECAgMBAAAAAAAAAAAAAAAAAAAAAAAAAAEGBwEFBAEBCAECAwEAAAAAAAAAAAAAAAAAAAAAAAAAAQgBBwEEAQgJAQICAQAAAAAAAAAAAAAAAAAAAAAAAAEICAEHAQQBCQYBAgIBAAAAAAAAAAAAAAAAAAAAAAAAAAEGCQkBBQEGAQUBAgEAAAAAAAAAAAAAAAAAAAAAAAAAAAEBBgYBAQEBAQABAAAAAAAAAAAAAAAAAAAAAAAAAAAAAQcBAQEDAQEAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAABAwMBAgcHAQAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAQMDAwIBAQEBAQAAAAAAAAAAAAAAAAAAAAAAAAAAAAABBAIDAgEKCgECAQAAAAAAAAAAAAAAAAAAAAAAAAAAAAECAQEBAQkJAQIBAAAAAAAAAAAAAAAAAAAAAAAAAAAAAQECAgICAQECAQoBAAAAAAAAAAAAAAAAAAAAAAAAAAABAQEBAQICAgEKCgEAAAAAAAAAAAAAAAAAAAAAAAAAAQEBAQEBAQEBCgoKAQAAAAAAAAAAAAAAAAAAAAAAAAABAQEBAQEBAQEBAQEAAAAAAAAAAAAAAAAAAAAAAAAAAAABAQEBAQEBAQEBAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAQEBAQEBAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA==" - }, - "palette" : { - "originalArgb8888" : [ -14671840, -11431408, -9326048, -802016, -3964416, -5086944, -789517, -810399, -1863087, -10403552 ], - "convertedRgb565" : [ 8452, 21634, 30084, -2556, -15360, -19708, -2146, -2804, -7030, 25092 ] } }, "diagnostics" : [ ] @@ -1522,14 +1522,14 @@ "last_modified" : 1775797786714, "fingerprint" : "5e0954447699c6d5eac7550f1a10cf520efcddad0b9fbd9a716434da9d9550d4", "metadata" : { + "palette" : { + "originalArgb8888" : [ -14671840, -11431408, -9326048, -802016, -3964416, -5086944, -789517, -810399, -1863087, -10403552, -5078447 ], + "convertedRgb565" : [ 8452, 21634, 30084, -2556, -15360, -19708, -2146, -2804, -7030, 25092, -19446 ] + }, "tile" : { "width" : 32, "height" : 32, "paletteIndices" : "AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAABAQEBAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAQEBAQICAwMBAQAAAAAAAAAAAAAAAAAAAAAAAAAAAAEEBAQBAgIDAwMCAQABAQAAAAAAAAAAAAAAAAAAAAAAAQUFBAQBAgIDAgIBAQMBAAAAAAAAAAAAAAAAAAAAAAAAAQEFBAUBAgICAgIDAwEAAAAAAAAAAAAAAAAAAAAAAAABBgEFBQUBAgECAgIBAAAAAAAAAAAAAAAAAAAAAAAAAAEGBwEFBAUBCAEBAQEAAAAAAAAAAAAAAAAAAAAAAAAAAQgBBwEEBQEJAQEFBQEAAAAAAAAAAAAAAAAAAAAAAAEICAEHCAEEBQEBBQEBAAAAAAAAAAAAAAAAAAAAAAAAAAEGCQkGBgEBAQEBAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAEBBgYGAQIDAQAAAAAAAAAAAAAAAAAAAAAAAAAAAAABCQEBAQEBAQEHAQAAAAAAAAAAAAAAAAAAAAAAAAAAAQEBBwcDAgEKCgEBAAAAAAAAAAAAAAAAAAAAAAAAAAABAgIBAwMCAQkJAQEAAAAAAAAAAAAAAAAAAAAAAAAAAQEBAQIBAgMCAQEBCgEAAAAAAAAAAAAAAAAAAAAAAAABCwsKAQIBAQECAgEKAQAAAAAAAAAAAAAAAAAAAAAAAAABCwsKAQICAgIBCgoBAAAAAAAAAAAAAAAAAAAAAAAAAAABAQEBAQEBAQEBAQAAAAAAAAAAAAAAAAAAAAAAAAAAAQEBAQEBAQEBAQEBAAAAAAAAAAAAAAAAAAAAAAAAAAABAQEBAQEBAQEBAQEAAAAAAAAAAAAAAAAAAAAAAAAAAAABAQEBAQEBAQEBAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAQEBAQEBAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA==" - }, - "palette" : { - "originalArgb8888" : [ -14671840, -11431408, -9326048, -802016, -3964416, -5086944, -789517, -810399, -1863087, -10403552, -5078447 ], - "convertedRgb565" : [ 8452, 21634, 30084, -2556, -15360, -19708, -2146, -2804, -7030, 25092, -19446 ] } }, "diagnostics" : [ ] @@ -1540,14 +1540,14 @@ "last_modified" : 1775797786716, "fingerprint" : "6104ba7f216a937994d478ed07766ec28f48ad72fdd6620508535a1f877b8ddb", "metadata" : { + "palette" : { + "originalArgb8888" : [ -14671840, -11431408, -9326048, -802016, -3964416, -5086944, -789517, -810399, -1863087, -10403552, -5078447 ], + "convertedRgb565" : [ 8452, 21634, 30084, -2556, -15360, -19708, -2146, -2804, -7030, 25092, -19446 ] + }, "tile" : { "width" : 32, "height" : 32, "paletteIndices" : "AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAABAQEBAAAAAAEBAAAAAAAAAAAAAAAAAAAAAAAAAAEBAQICAwMBAQEBAwEAAAAAAAAAAAAAAAAAAAAAAAABBAQBAgIDAwMCAQMDAQAAAAAAAAAAAAAAAAAAAAAAAQUFBAQBAgIDAgICAwIBAAAAAAAAAAAAAAAAAAAAAAABBQEFBAUBAgICAgMCAQAAAAAAAAAAAAAAAAAAAAAAAAABBgEFBQUBAgECAgIBAAAAAAAAAAAAAAAAAAAAAAAAAAEGBwEFBAUBCAEBAQAAAAAAAAAAAAAAAAAAAAAAAAAAAQgBBwEEBQEJAQEAAAAAAAAAAAAAAAAAAAAAAAAAAAEICAEHCQEEBQEFAQAAAAAAAAAAAAAAAAAAAAAAAAAAAAEGCQkGBgEBAQEBAAAAAAAAAAAAAAAAAAAAAAAAAAABAQEBBgYGAQIDAgEBAAAAAAAAAAAAAAAAAAAAAAAAAAEJAQEBAQEBAgIBAQAAAAAAAAAAAAAAAAAAAAAAAAAAAAEBBwcDAgIBAQoKAQAAAAAAAAAAAAAAAAAAAAAAAAAAAQQBAwMDAgIBCQkBAAAAAAAAAAAAAAAAAAAAAAAAAAEBAgECAwMCAQEBAQEAAAAAAAAAAAAAAAAAAAAAAAABCwYBAgEBAQECAgEKAQAAAAAAAAAAAAAAAAAAAAAAAAELCgYBAgICAgEBAQEAAAAAAAAAAAAAAAAAAAAAAAAAAAEKCgoBAQEBAQEBAQAAAAAAAAAAAAAAAAAAAAAAAAAAAQEBAQEBAQEBAQEBAAAAAAAAAAAAAAAAAAAAAAAAAAAAAQEBAQEBAQEBAQAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAEBAQEBAQAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA==" - }, - "palette" : { - "originalArgb8888" : [ -14671840, -11431408, -9326048, -802016, -3964416, -5086944, -789517, -810399, -1863087, -10403552, -5078447 ], - "convertedRgb565" : [ 8452, 21634, 30084, -2556, -15360, -19708, -2146, -2804, -7030, 25092, -19446 ] } }, "diagnostics" : [ ] @@ -1602,14 +1602,14 @@ "last_modified" : 1776965154257, "fingerprint" : "8771c3e294d0edbc8dd3aaa6995a6db32166ae6bfb3e063170cc79b298d17e71", "metadata" : { + "palette" : { + "originalArgb8888" : [ -12019640 ], + "convertedRgb565" : [ 19657 ] + }, "tile" : { "width" : 8, "height" : 8, "paletteIndices" : "AQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQ==" - }, - "palette" : { - "originalArgb8888" : [ -12019640 ], - "convertedRgb565" : [ 19657 ] } }, "diagnostics" : [ ] @@ -1620,14 +1620,14 @@ "last_modified" : 1776965154257, "fingerprint" : "5d81eef8be13043330b42b546e10beed8ba00dfaa42df67477a8778c2b9484d7", "metadata" : { + "palette" : { + "originalArgb8888" : [ -12019640, -12552128, -14129088, -14133200, -14145496, -7835584, -5730208, -10465232 ], + "convertedRgb565" : [ 19657, 17352, 11080, 10950, 10565, -29816, -21364, 25222 ] + }, "tile" : { "width" : 8, "height" : 8, "paletteIndices" : "AQEBAQEBAQEBAQEBAQICAgECAgICAgICAgMEBQUFBQQDBAUGBgYGBQMEBQYGBwcIAwQFCAYGCAgBAwUFCAgIBw==" - }, - "palette" : { - "originalArgb8888" : [ -12019640, -12552128, -14129088, -14133200, -14145496, -7835584, -5730208, -10465232 ], - "convertedRgb565" : [ 19657, 17352, 11080, 10950, 10565, -29816, -21364, 25222 ] } }, "diagnostics" : [ ] @@ -1638,14 +1638,14 @@ "last_modified" : 1776965154258, "fingerprint" : "3250840c4fe08c134ea966ce7c8fcaccae2c2a45660d7173c5e262a2e5076548", "metadata" : { + "palette" : { + "originalArgb8888" : [ -12552128, -14133200, -14145496, -10465232, -5730208, -7835584 ], + "convertedRgb565" : [ 17352, 10950, 10565, 25222, -21364, -29816 ] + }, "tile" : { "width" : 8, "height" : 8, "paletteIndices" : "AQEBAQECAwMBAQEBAgMEBQEBAQIDBAUFAQIDAwQEBAQDAwYFBQUFBQQGBQUGBgYGBQUFBgYFBQUFBgYGBQUGBg==" - }, - "palette" : { - "originalArgb8888" : [ -12552128, -14133200, -14145496, -10465232, -5730208, -7835584 ], - "convertedRgb565" : [ 17352, 10950, 10565, 25222, -21364, -29816 ] } }, "diagnostics" : [ ] @@ -1656,14 +1656,14 @@ "last_modified" : 1776965154258, "fingerprint" : "fe3ab2b7eb3b10a042de14484d53e718e6b505edb1ad19053668565bfe3a8f25", "metadata" : { + "palette" : { + "originalArgb8888" : [ -14145496, -14133200, -12552128, -5730208, -10465232, -7835584 ], + "convertedRgb565" : [ 10565, 10950, 17352, -21364, 25222, -29816 ] + }, "tile" : { "width" : 8, "height" : 8, "paletteIndices" : "AQECAwMDAwMEBQECAwMDAwQEBQECAwMDBQUFBQEBAgMEBAQEBAYBAQYGBgYEBAYFBAQEBgYEBAQGBgQEBgYGBA==" - }, - "palette" : { - "originalArgb8888" : [ -14145496, -14133200, -12552128, -5730208, -10465232, -7835584 ], - "convertedRgb565" : [ 10565, 10950, 17352, -21364, 25222, -29816 ] } }, "diagnostics" : [ ] @@ -1674,14 +1674,14 @@ "last_modified" : 1776965154259, "fingerprint" : "7fcbf90e1e9a69d6ce3be80ea1901d66c9992f68dc72e4c636dcd2ad52fa2898", "metadata" : { + "palette" : { + "originalArgb8888" : [ -12019640, -12552128, -14133200, -14145496, -14129088, -7835584, -10465232, -5730208 ], + "convertedRgb565" : [ 19657, 17352, 10950, 10565, 11080, -29816, 25222, -21364 ] + }, "tile" : { "width" : 8, "height" : 8, "paletteIndices" : "AQEBAQEBAQECAgIBAQEBAQICAgICAgIBAwQEBAQDBQIEBgYGBgQDBQcICAYGBAMFBwcGBgcEAwUIBwcHBAQFAQ==" - }, - "palette" : { - "originalArgb8888" : [ -12019640, -12552128, -14133200, -14145496, -14129088, -7835584, -10465232, -5730208 ], - "convertedRgb565" : [ 19657, 17352, 10950, 10565, 11080, -29816, 25222, -21364 ] } }, "diagnostics" : [ ] @@ -1692,14 +1692,14 @@ "last_modified" : 1776965154259, "fingerprint" : "451fc8d646049944d5aa7c7dc254636eec0151aaff6e2051059304b9d6ebc31e", "metadata" : { + "palette" : { + "originalArgb8888" : [ -12019640, -14129088, -14133200, -14145496, -10465232, -5730208, -7835584 ], + "convertedRgb565" : [ 19657, 11080, 10950, 10565, 25222, -21364, -29816 ] + }, "tile" : { "width" : 8, "height" : 8, "paletteIndices" : "AQIDBAQFBgYBAQIDBAYGBwEBAQMEBgcHAQEBBAQGBwcBAQQFBAYHBwEEBwUEBgcHBAcGBQQGBwcEBwYFBAYHBw==" - }, - "palette" : { - "originalArgb8888" : [ -12019640, -14129088, -14133200, -14145496, -10465232, -5730208, -7835584 ], - "convertedRgb565" : [ 19657, 11080, 10950, 10565, 25222, -21364, -29816 ] } }, "diagnostics" : [ ] @@ -1710,14 +1710,14 @@ "last_modified" : 1776965154260, "fingerprint" : "aa757df4600823ec6655235a1081061777124ccee74b31481bbe402e53635f53", "metadata" : { + "palette" : { + "originalArgb8888" : [ -7835584, -5730208, -10465232, -14145496 ], + "convertedRgb565" : [ -29816, -21364, 25222, 10565 ] + }, "tile" : { "width" : 8, "height" : 8, "paletteIndices" : "AQECAwMBAQEBAgIBAwMBAgICAQEBAwMCAgIBAQIDBAMCAgEBAgMEBAICAQECAwQEAgIBAQIDBAMCAgIBAwQDAg==" - }, - "palette" : { - "originalArgb8888" : [ -7835584, -5730208, -10465232, -14145496 ], - "convertedRgb565" : [ -29816, -21364, 25222, 10565 ] } }, "diagnostics" : [ ] @@ -1728,14 +1728,14 @@ "last_modified" : 1776965154260, "fingerprint" : "38162157f5685cce25b835d3a2caee3465fd2ec3ee5db2a5089d7d5ae5ea3bb7", "metadata" : { + "palette" : { + "originalArgb8888" : [ -7835584, -10465232, -5730208, -14145496 ], + "convertedRgb565" : [ -29816, 25222, -21364, 10565 ] + }, "tile" : { "width" : 8, "height" : 8, "paletteIndices" : "AQEBAgIDAQEDAQICAQMDAQMCAgEBAQMDAgQCAwEBAwMEBAIDAQEDAwQEAgMBAQMDAgQCAwEBAwMDAgQCAQMDAw==" - }, - "palette" : { - "originalArgb8888" : [ -7835584, -10465232, -5730208, -14145496 ], - "convertedRgb565" : [ -29816, 25222, -21364, 10565 ] } }, "diagnostics" : [ ] @@ -1746,14 +1746,14 @@ "last_modified" : 1776965154260, "fingerprint" : "8cab5b3d553af9ed371bd19fc624763accc90e5d926d300ba31dd8d9d6bab803", "metadata" : { + "palette" : { + "originalArgb8888" : [ -5730208, -10465232, -14145496, -14133200, -14129088, -12019640, -7835584 ], + "convertedRgb565" : [ -21364, 25222, 10565, 10950, 11080, 19657, -29816 ] + }, "tile" : { "width" : 8, "height" : 8, "paletteIndices" : "AQECAwMEBQYHAQEDBAUGBgcHAQMEBgYGBwcBAwMGBgYHBwEDAgMGBgcHAQMCBwMGBwcBAwIBBwMHBwEDAgEHAw==" - }, - "palette" : { - "originalArgb8888" : [ -5730208, -10465232, -14145496, -14133200, -14129088, -12019640, -7835584 ], - "convertedRgb565" : [ -21364, 25222, 10565, 10950, 11080, 19657, -29816 ] } }, "diagnostics" : [ ] @@ -1764,14 +1764,14 @@ "last_modified" : 1776965154261, "fingerprint" : "d9ff5a6df0f65f5fcfb8f22376beeb266d429e2c6e9c82f51c12bc6ee4c3fcdc", "metadata" : { + "palette" : { + "originalArgb8888" : [ -14145496, -10465232, -7835584, -5730208, -14133200, -14129088, -12019640 ], + "convertedRgb565" : [ 10565, 25222, -29816, -21364, 10950, 11080, 19657 ] + }, "tile" : { "width" : 8, "height" : 8, "paletteIndices" : "AQIDAgIBBAMFAQECAgEEBAUGBQECAgEEBwYFBQECAQEHBwYGBQEBAgcHBwYFAQMDBwcHBwEBAwMHBwcFAQICAw==" - }, - "palette" : { - "originalArgb8888" : [ -14145496, -10465232, -7835584, -5730208, -14133200, -14129088, -12019640 ], - "convertedRgb565" : [ 10565, 25222, -29816, -21364, 10950, 11080, 19657 ] } }, "diagnostics" : [ ] @@ -1782,14 +1782,14 @@ "last_modified" : 1776965154261, "fingerprint" : "b9ff45c77f7779a6acebcc537c2ddac0e27e91162b656a04dc4772ec5f24fc26", "metadata" : { + "palette" : { + "originalArgb8888" : [ -7835584, -5730208, -10465232, -14145496 ], + "convertedRgb565" : [ -29816, -21364, 25222, 10565 ] + }, "tile" : { "width" : 8, "height" : 8, "paletteIndices" : "AQICAwMBAQIBAQMDAgIBAQIBAQEBAgIBAgICAgEBAgIEAwMCAgEBAQMEAwMCAgEBAQMEAwMDAgIBAwMEAwMDAw==" - }, - "palette" : { - "originalArgb8888" : [ -7835584, -5730208, -10465232, -14145496 ], - "convertedRgb565" : [ -29816, -21364, 25222, 10565 ] } }, "diagnostics" : [ ] @@ -1800,14 +1800,14 @@ "last_modified" : 1776965154261, "fingerprint" : "43f370324fedccda888d49409e2a64f182f08b4143b4bdd5bafaf498feebd21a", "metadata" : { + "palette" : { + "originalArgb8888" : [ -5730208, -7835584, -10465232, -14145496 ], + "convertedRgb565" : [ -21364, -29816, 25222, 10565 ] + }, "tile" : { "width" : 8, "height" : 8, "paletteIndices" : "AQICAwMBAQICAgEBAwMCAgIBAQICAgIBAQECAgEBAQECAgIBAQMDBAICAQEDAwQDAQEDAwMEAwIDAwMDBAMDAg==" - }, - "palette" : { - "originalArgb8888" : [ -5730208, -7835584, -10465232, -14145496 ], - "convertedRgb565" : [ -21364, -29816, 25222, 10565 ] } }, "diagnostics" : [ ] @@ -1818,14 +1818,14 @@ "last_modified" : 1776965154262, "fingerprint" : "cb047e655f4e196f22ca0048149df5dcb959f895faeaeb94920182d4a2d16b38", "metadata" : { + "palette" : { + "originalArgb8888" : [ -7835584, -5730208, -14145496, -10465232, -14133200, -14129088, -12019640 ], + "convertedRgb565" : [ -29816, -21364, 10565, 25222, 10950, 11080, 19657 ] + }, "tile" : { "width" : 8, "height" : 8, "paletteIndices" : "AQIDBAQBBAMCAgMEBAMDBQIDBAQDBQYFAwMEAwUFBgcEAwMFBgYHBwEBAwUGBwcHAQEDAwcHBwcBBAQDBQcHBw==" - }, - "palette" : { - "originalArgb8888" : [ -7835584, -5730208, -14145496, -10465232, -14133200, -14129088, -12019640 ], - "convertedRgb565" : [ -29816, -21364, 10565, 25222, 10950, 11080, 19657 ] } }, "diagnostics" : [ ] @@ -1836,14 +1836,14 @@ "last_modified" : 1776965154262, "fingerprint" : "25eba17b67dd5159f5fb9d3edd531d54a44d1c76f997385840dac53517b98886", "metadata" : { + "palette" : { + "originalArgb8888" : [ -12019640, -14145496, -7835584, -10465232, -14133200, -14129088 ], + "convertedRgb565" : [ 19657, 10565, -29816, 25222, 10950, 11080 ] + }, "tile" : { "width" : 8, "height" : 8, "paletteIndices" : "AQEBAgMDBAQBAQIDAwMDBAEBAgMDAwMEAQECAwMEAgQBAQIEAgUFAgEBBQUGBQYFAQEBAQEGAQYBAQEBAQEBAQ==" - }, - "palette" : { - "originalArgb8888" : [ -12019640, -14145496, -7835584, -10465232, -14133200, -14129088 ], - "convertedRgb565" : [ 19657, 10565, -29816, 25222, 10950, 11080 ] } }, "diagnostics" : [ ] @@ -1854,14 +1854,14 @@ "last_modified" : 1776965154262, "fingerprint" : "32ca96c14290de8009fd2db623f55514bed2345b7d5881a80dd3fe6235012854", "metadata" : { + "palette" : { + "originalArgb8888" : [ -10465232, -14145496, -14133200, -7835584, -14129088, -12019640 ], + "convertedRgb565" : [ 25222, 10565, 10950, -29816, 11080, 19657 ] + }, "tile" : { "width" : 8, "height" : 8, "paletteIndices" : "AQEBAgEBAgICAQICAQIBAQICAwICAQEEAgMDAwIBAQQDAwUDAwIBAQUFBgUFAgEEBgYGBgYDAgEGBgYGBgYDAg==" - }, - "palette" : { - "originalArgb8888" : [ -10465232, -14145496, -14133200, -7835584, -14129088, -12019640 ], - "convertedRgb565" : [ 25222, 10565, 10950, -29816, 11080, 19657 ] } }, "diagnostics" : [ ] @@ -1872,14 +1872,14 @@ "last_modified" : 1776965154263, "fingerprint" : "7a093fe00c805bcf38d4facff14a6d4c2b8baeaa2d553fa8d3db9f2d76b32f3b", "metadata" : { + "palette" : { + "originalArgb8888" : [ -14145496, -10465232, -7835584, -14133200, -14129088, -12019640 ], + "convertedRgb565" : [ 10565, 25222, -29816, 10950, 11080, 19657 ] + }, "tile" : { "width" : 8, "height" : 8, "paletteIndices" : "AQECAgECAgICAgECAQECAQMCAgEBBAEBAwICAQQEBAECAgEEBAUEBAMCAQUFBgUFAgEEBgYGBgYBBAYGBgYGBg==" - }, - "palette" : { - "originalArgb8888" : [ -14145496, -10465232, -7835584, -14133200, -14129088, -12019640 ], - "convertedRgb565" : [ 10565, 25222, -29816, 10950, 11080, 19657 ] } }, "diagnostics" : [ ] @@ -1890,14 +1890,14 @@ "last_modified" : 1776965154263, "fingerprint" : "77c5277220421226d16f58b1bcfb4eaf157fa4f6c740c5aaebefaf88fb91c22e", "metadata" : { + "palette" : { + "originalArgb8888" : [ -10465232, -7835584, -14145496, -12019640, -14133200, -14129088 ], + "convertedRgb565" : [ 25222, -29816, 10565, 19657, 10950, 11080 ] + }, "tile" : { "width" : 8, "height" : 8, "paletteIndices" : "AQECAgMEBAQBAgICAgMEBAECAgICAwQEAQMBAgIDBAQDBQUDAQMEBAUGBQYFBQQEBgQGBAQEBAQEBAQEBAQEBA==" - }, - "palette" : { - "originalArgb8888" : [ -10465232, -7835584, -14145496, -12019640, -14133200, -14129088 ], - "convertedRgb565" : [ 25222, -29816, 10565, 19657, 10950, 11080 ] } }, "diagnostics" : [ ] -- 2.47.2 From 85a224fc7b7d6a8986ddffcf807eac38f825b40c Mon Sep 17 00:00:00 2001 From: bQUARKz Date: Wed, 6 May 2026 03:40:55 +0100 Subject: [PATCH 13/37] basic for analyse --- .../workspaces/BuilderPipelineService.java | 26 ++- .../stages/FrontendPhasePipelineStage.java | 9 + .../MainProjectPipelineIntegrationTest.java | 33 ++++ .../utilities/SourceProviderFactory.java | 38 +++- prometeu-lsp/prometeu-lsp-v1/build.gradle.kts | 1 + .../CompilerLanguageServiceBridge.java | 151 +++++++++++++--- .../protocol/PrometeuLanguageServer.java | 28 ++- .../mapping/Lsp4jProtocolMessageMapper.java | 5 + .../mapping/ProtocolMessageMapper.java | 1 + .../CompilerLanguageServiceBridgeTest.java | 52 ++++++ .../protocol/PrometeuLanguageServerTest.java | 168 ++++++++++++++++++ 11 files changed, 466 insertions(+), 46 deletions(-) create mode 100644 prometeu-lsp/prometeu-lsp-v1/src/test/java/p/studio/lsp/services/compiler/CompilerLanguageServiceBridgeTest.java create mode 100644 prometeu-lsp/prometeu-lsp-v1/src/test/java/p/studio/lsp/services/protocol/PrometeuLanguageServerTest.java diff --git a/prometeu-compiler/prometeu-build-pipeline/src/main/java/p/studio/compiler/workspaces/BuilderPipelineService.java b/prometeu-compiler/prometeu-build-pipeline/src/main/java/p/studio/compiler/workspaces/BuilderPipelineService.java index 661cf7dd..c0f35f7d 100644 --- a/prometeu-compiler/prometeu-build-pipeline/src/main/java/p/studio/compiler/workspaces/BuilderPipelineService.java +++ b/prometeu-compiler/prometeu-build-pipeline/src/main/java/p/studio/compiler/workspaces/BuilderPipelineService.java @@ -57,7 +57,7 @@ public class BuilderPipelineService { public AnalysisSnapshot analyze( final BuilderPipelineContext ctx, final LogAggregator logs) { - final var diagnostics = run(ctx, logs, analyses, new ArrayList<>()); + final var diagnostics = run(ctx, logs, analyses, new ArrayList<>(), false); return new AnalysisSnapshot( ctx.resolvedWorkspace.frontendSpec(), diagnostics, @@ -70,7 +70,10 @@ public class BuilderPipelineService { final BuilderPipelineContext ctx, final LogAggregator logs) { final var analysisSnapshot = this.analyze(ctx, logs); - final var diagnostics = run(ctx, logs, compile, new ArrayList<>(analysisSnapshot.diagnostics())); + if (hasErrors(analysisSnapshot.diagnostics())) { + throw new BuildException("issues found on pipeline stage: analyze"); + } + final var diagnostics = run(ctx, logs, compile, new ArrayList<>(analysisSnapshot.diagnostics()), true); return new CompileResult( analysisSnapshot, diagnostics, @@ -84,7 +87,7 @@ public class BuilderPipelineService { final BuilderPipelineContext ctx, final LogAggregator logs) { final var compileResult = this.compile(ctx, logs); - final var diagnostics = run(ctx, logs, build, new ArrayList<>(compileResult.diagnostics())); + final var diagnostics = run(ctx, logs, build, new ArrayList<>(compileResult.diagnostics()), true); return new BuildResult( compileResult, diagnostics, @@ -95,19 +98,32 @@ public class BuilderPipelineService { final BuilderPipelineContext ctx, final LogAggregator logs, final List stages, - final List diagnostics) { + final List diagnostics, + final boolean failFast) { for (final var builderPipelineStage : stages) { final var issues = builderPipelineStage.run(ctx, logs); diagnostics.addAll(issues.asCollection()); printIssues(issues, logs); if (issues.hasErrors()) { - throw new BuildException("issues found on pipeline stage: " + builderPipelineStage.getClass().getSimpleName()); + if (failFast) { + throw new BuildException("issues found on pipeline stage: " + builderPipelineStage.getClass().getSimpleName()); + } + break; } } logs.using(log).info("builder pipeline completed successfully"); return List.copyOf(diagnostics); } + private boolean hasErrors(final List diagnostics) { + for (final var diagnostic : diagnostics) { + if (diagnostic.isError()) { + return true; + } + } + return false; + } + private void printIssues( final ReadOnlyCollection issues, final LogAggregator logs) { diff --git a/prometeu-compiler/prometeu-build-pipeline/src/main/java/p/studio/compiler/workspaces/stages/FrontendPhasePipelineStage.java b/prometeu-compiler/prometeu-build-pipeline/src/main/java/p/studio/compiler/workspaces/stages/FrontendPhasePipelineStage.java index 6a039522..4b370e6a 100644 --- a/prometeu-compiler/prometeu-build-pipeline/src/main/java/p/studio/compiler/workspaces/stages/FrontendPhasePipelineStage.java +++ b/prometeu-compiler/prometeu-build-pipeline/src/main/java/p/studio/compiler/workspaces/stages/FrontendPhasePipelineStage.java @@ -48,6 +48,11 @@ public class FrontendPhasePipelineStage implements PipelineStage { final var span = diagnostic.getSpan(); issues.report(builder -> builder .error(diagnostic.getSeverity().isError()) + .phase(diagnostic.getPhase().id()) + .code(diagnostic.getCode()) + .fileId(span.getFileId().isNone() ? null : span.getFileId().getId()) + .start(safeToInt(span.getStart())) + .end(safeToInt(span.getEnd())) .message("[BUILD] %s :: %s @ %s:[%d,%d)".formatted( diagnostic.getCode(), diagnostic.getMessage(), @@ -56,4 +61,8 @@ public class FrontendPhasePipelineStage implements PipelineStage { span.getEnd()))); } } + + private int safeToInt(final long value) { + return value > Integer.MAX_VALUE ? Integer.MAX_VALUE : (int) Math.max(0L, value); + } } diff --git a/prometeu-compiler/prometeu-build-pipeline/src/test/java/p/studio/compiler/integration/MainProjectPipelineIntegrationTest.java b/prometeu-compiler/prometeu-build-pipeline/src/test/java/p/studio/compiler/integration/MainProjectPipelineIntegrationTest.java index 164ececa..eea50a34 100644 --- a/prometeu-compiler/prometeu-build-pipeline/src/test/java/p/studio/compiler/integration/MainProjectPipelineIntegrationTest.java +++ b/prometeu-compiler/prometeu-build-pipeline/src/test/java/p/studio/compiler/integration/MainProjectPipelineIntegrationTest.java @@ -3,12 +3,15 @@ package p.studio.compiler.integration; import org.junit.jupiter.api.Test; import p.studio.compiler.messages.BuilderPipelineConfig; import p.studio.compiler.models.BuilderPipelineContext; +import p.studio.compiler.source.identifiers.FileId; +import p.studio.compiler.utilities.SourceProviderFactory; import p.studio.compiler.workspaces.BuilderPipelineService; import p.studio.utilities.logs.LogAggregator; import java.io.IOException; import java.nio.file.Files; import java.nio.file.Path; +import java.util.Map; import static org.junit.jupiter.api.Assertions.*; @@ -32,6 +35,36 @@ class MainProjectPipelineIntegrationTest { assertFalse(Files.exists(outputPath), "analyze must not write output: " + outputPath); } + @Test + void analyzeShouldReturnStructuredDiagnosticsForOverlayDocumentWithoutThrowing() throws IOException { + final var projectRoot = projectRoot(); + final var documentPath = projectRoot.resolve("src").resolve("main.pbs").toAbsolutePath().normalize(); + final var logs = bufferedLogs(); + final var invalidOverlay = """ + fn frame() -> void { + let broken: int = ; + } + """; + final var context = BuilderPipelineContext.fromConfig(new BuilderPipelineConfig( + false, + projectRoot.toString(), + "core-v1", + SourceProviderFactory.overlayUtf8(Map.of(documentPath, invalidOverlay)))); + + final var snapshot = assertDoesNotThrow( + () -> BuilderPipelineService.INSTANCE.analyze(context, logs), + () -> "analyze unexpectedly failed for overlay " + documentPath); + + final var documentDiagnostics = snapshot.diagnostics().stream() + .filter(issue -> issue.getFileId() != null) + .filter(issue -> issue.getFileId() >= 0 && issue.getFileId() < snapshot.fileTable().size()) + .filter(issue -> snapshot.fileTable().get(new FileId(issue.getFileId())).getCanonPath().toAbsolutePath().normalize().equals(documentPath)) + .toList(); + + assertFalse(documentDiagnostics.isEmpty(), "overlay analysis must surface diagnostics for " + documentPath); + assertTrue(documentDiagnostics.stream().anyMatch(issue -> issue.isError() && issue.getCode() != null && issue.getStart() != null && issue.getEnd() != null)); + } + @Test void compileShouldProduceInMemoryBytecodeWithoutWritingProgramBytecode() throws IOException { final var projectRoot = projectRoot(); diff --git a/prometeu-compiler/prometeu-compiler-core/src/main/java/p/studio/compiler/utilities/SourceProviderFactory.java b/prometeu-compiler/prometeu-compiler-core/src/main/java/p/studio/compiler/utilities/SourceProviderFactory.java index 852f0425..6079e30b 100644 --- a/prometeu-compiler/prometeu-compiler-core/src/main/java/p/studio/compiler/utilities/SourceProviderFactory.java +++ b/prometeu-compiler/prometeu-compiler-core/src/main/java/p/studio/compiler/utilities/SourceProviderFactory.java @@ -1,8 +1,11 @@ package p.studio.compiler.utilities; import java.io.IOException; +import java.nio.charset.StandardCharsets; import java.nio.file.Files; import java.nio.file.Path; +import java.util.HashMap; +import java.util.Map; import java.util.Objects; @FunctionalInterface @@ -24,5 +27,38 @@ public interface SourceProviderFactory { }; } - // more providers can be added here, e.g., in-memory, etc. + static SourceProviderFactory overlayUtf8(final Map overrides) { + final Map bytesByPath = new HashMap<>(); + for (final var entry : Objects.requireNonNull(overrides, "overrides").entrySet()) { + bytesByPath.put( + normalize(entry.getKey()), + Objects.requireNonNull(entry.getValue(), "override text").getBytes(StandardCharsets.UTF_8)); + } + return overlay(bytesByPath, filesystem()); + } + + static SourceProviderFactory overlay( + final Map overrides, + final SourceProviderFactory fallback) { + final Map normalizedOverrides = new HashMap<>(); + for (final var entry : Objects.requireNonNull(overrides, "overrides").entrySet()) { + normalizedOverrides.put( + normalize(entry.getKey()), + Objects.requireNonNull(entry.getValue(), "override bytes").clone()); + } + final SourceProviderFactory safeFallback = Objects.requireNonNull(fallback, "fallback"); + return path -> { + final Path normalizedPath = normalize(path); + final byte[] override = normalizedOverrides.get(normalizedPath); + if (override != null) { + final byte[] immutableBytes = override.clone(); + return () -> immutableBytes; + } + return safeFallback.create(normalizedPath); + }; + } + + private static Path normalize(final Path path) { + return Objects.requireNonNull(path, "path").toAbsolutePath().normalize(); + } } diff --git a/prometeu-lsp/prometeu-lsp-v1/build.gradle.kts b/prometeu-lsp/prometeu-lsp-v1/build.gradle.kts index 082335f3..e73cc24e 100644 --- a/prometeu-lsp/prometeu-lsp-v1/build.gradle.kts +++ b/prometeu-lsp/prometeu-lsp-v1/build.gradle.kts @@ -4,6 +4,7 @@ plugins { dependencies { implementation(project(":prometeu-lsp:prometeu-lsp-api")) + implementation(project(":prometeu-compiler:prometeu-compiler-core")) implementation(project(":prometeu-compiler:prometeu-build-pipeline")) implementation(libs.lsp4j) } diff --git a/prometeu-lsp/prometeu-lsp-v1/src/main/java/p/studio/lsp/services/compiler/CompilerLanguageServiceBridge.java b/prometeu-lsp/prometeu-lsp-v1/src/main/java/p/studio/lsp/services/compiler/CompilerLanguageServiceBridge.java index ae4062aa..07b5cec2 100644 --- a/prometeu-lsp/prometeu-lsp-v1/src/main/java/p/studio/lsp/services/compiler/CompilerLanguageServiceBridge.java +++ b/prometeu-lsp/prometeu-lsp-v1/src/main/java/p/studio/lsp/services/compiler/CompilerLanguageServiceBridge.java @@ -1,22 +1,25 @@ package p.studio.lsp.services.compiler; +import p.studio.compiler.messages.BuilderPipelineConfig; +import p.studio.compiler.messages.BuildingIssue; +import p.studio.compiler.models.AnalysisSnapshot; +import p.studio.compiler.models.BuilderPipelineContext; +import p.studio.compiler.source.identifiers.FileId; +import p.studio.compiler.utilities.SourceProviderFactory; import p.studio.compiler.workspaces.BuilderPipelineService; import p.studio.lsp.messages.*; import p.studio.lsp.services.LanguageServiceBridge; +import p.studio.utilities.logs.LogAggregator; +import java.net.URI; +import java.nio.charset.StandardCharsets; +import java.nio.file.Path; +import java.util.ArrayList; import java.util.List; +import java.util.Map; import java.util.Objects; -public record CompilerLanguageServiceBridge( - BuilderPipelineService builderPipelineService) implements LanguageServiceBridge { - - public CompilerLanguageServiceBridge() { - this(BuilderPipelineService.INSTANCE); - } - - public CompilerLanguageServiceBridge(final BuilderPipelineService builderPipelineService) { - this.builderPipelineService = Objects.requireNonNull(builderPipelineService, "builderPipelineService"); - } +public record CompilerLanguageServiceBridge() implements LanguageServiceBridge { @Override public BaselineServerDescription describeServer(final LspProjectContext context) { @@ -33,16 +36,10 @@ public record CompilerLanguageServiceBridge( final String documentUri, final String text) { Objects.requireNonNull(context, "context"); - // Wave 1 keeps responses intentionally synthetic while hardening the bridge boundary. - final String message = "Compiler-backed baseline via " + builderPipelineService.getClass().getSimpleName(); - return new BaselineDocumentAnalysis(List.of(new BaselineDocumentIssue( - 0, - 0, - 0, - Math.max(1, firstLineLength(text)), - BaselineIssueSeverity.INFORMATION, - "Prometeu Studio", - message))); + final Path documentPath = normalizeDocumentPath(documentUri); + final String effectiveText = text == null ? "" : text; + final AnalysisSnapshot snapshot = analyzeProject(context, Map.of(documentPath, effectiveText)); + return new BaselineDocumentAnalysis(mapDiagnostics(snapshot, documentPath, effectiveText)); } @Override @@ -69,11 +66,115 @@ public record CompilerLanguageServiceBridge( return "Prometeu Studio saw save: " + documentUri; } - private int firstLineLength(final String text) { - if (text == null || text.isEmpty()) { - return 1; + private AnalysisSnapshot analyzeProject( + final LspProjectContext context, + final Map overlays) { + final BuilderPipelineContext pipelineContext = BuilderPipelineContext.fromConfig( + new BuilderPipelineConfig( + false, + context.projectRoot().toString(), + "core-v1", + SourceProviderFactory.overlayUtf8(overlays))); + return BuilderPipelineService.INSTANCE.analyze(pipelineContext, LogAggregator.empty()); + } + + private List mapDiagnostics( + final AnalysisSnapshot snapshot, + final Path documentPath, + final String text) { + final ArrayList issues = new ArrayList<>(); + final DocumentPositionMapper positionMapper = new DocumentPositionMapper(text); + for (final BuildingIssue diagnostic : snapshot.diagnostics()) { + if (diagnostic.getFileId() == null || diagnostic.getFileId() < 0) { + continue; + } + final int fileIndex = diagnostic.getFileId(); + if (fileIndex >= snapshot.fileTable().size()) { + continue; + } + final var sourceHandle = snapshot.fileTable().get(new FileId(fileIndex)); + if (!sourceHandle.getCanonPath().toAbsolutePath().normalize().equals(documentPath)) { + continue; + } + issues.add(toBaselineIssue(diagnostic, positionMapper)); + } + return List.copyOf(issues); + } + + private BaselineDocumentIssue toBaselineIssue( + final BuildingIssue diagnostic, + final DocumentPositionMapper positionMapper) { + final int startOffset = diagnostic.getStart() == null ? 0 : diagnostic.getStart(); + final int endOffset = diagnostic.getEnd() == null ? startOffset : Math.max(startOffset, diagnostic.getEnd()); + final DocumentPosition start = positionMapper.positionOf(startOffset); + final DocumentPosition end = positionMapper.positionOf(endOffset); + return new BaselineDocumentIssue( + start.line(), + start.character(), + end.line(), + end.character(), + diagnostic.isError() ? BaselineIssueSeverity.ERROR : BaselineIssueSeverity.WARNING, + diagnostic.getCode() == null || diagnostic.getCode().isBlank() ? "Prometeu Studio" : diagnostic.getCode(), + diagnostic.getMessage()); + } + + private Path normalizeDocumentPath(final String documentUri) { + return Path.of(URI.create(Objects.requireNonNull(documentUri, "documentUri"))).toAbsolutePath().normalize(); + } + + private record DocumentPosition( + int line, + int character) { + } + + private static final class DocumentPositionMapper { + private final String text; + + private DocumentPositionMapper(final String text) { + this.text = Objects.requireNonNull(text, "text"); + } + + private DocumentPosition positionOf(final Integer byteOffset) { + if (byteOffset == null || byteOffset <= 0 || text.isEmpty()) { + return new DocumentPosition(0, 0); + } + final int target = Math.min(byteOffset, text.getBytes(StandardCharsets.UTF_8).length); + int utf8Offset = 0; + int line = 0; + int character = 0; + for (int index = 0; index < text.length(); ) { + if (utf8Offset >= target) { + return new DocumentPosition(line, character); + } + final int codePoint = text.codePointAt(index); + final int utf16Width = Character.charCount(codePoint); + final int utf8Width = utf8Length(codePoint); + if (utf8Offset + utf8Width > target) { + return new DocumentPosition(line, character); + } + utf8Offset += utf8Width; + if (codePoint == '\n') { + line++; + character = 0; + } else { + character += utf16Width; + } + index += utf16Width; + } + return new DocumentPosition(line, character); + } + + private int utf8Length(final int codePoint) { + if (codePoint <= 0x7F) { + return 1; + } + if (codePoint <= 0x7FF) { + return 2; + } + if (codePoint <= 0xFFFF) { + return 3; + } + return 4; } - final int newline = text.indexOf('\n'); - return newline < 0 ? text.length() : newline; } } diff --git a/prometeu-lsp/prometeu-lsp-v1/src/main/java/p/studio/lsp/services/protocol/PrometeuLanguageServer.java b/prometeu-lsp/prometeu-lsp-v1/src/main/java/p/studio/lsp/services/protocol/PrometeuLanguageServer.java index aa394d19..58b9aff1 100644 --- a/prometeu-lsp/prometeu-lsp-v1/src/main/java/p/studio/lsp/services/protocol/PrometeuLanguageServer.java +++ b/prometeu-lsp/prometeu-lsp-v1/src/main/java/p/studio/lsp/services/protocol/PrometeuLanguageServer.java @@ -1,14 +1,12 @@ package p.studio.lsp.services.protocol; -import org.eclipse.lsp4j.*; -import org.eclipse.lsp4j.services.LanguageClient; -import org.eclipse.lsp4j.services.LanguageClientAware; -import org.eclipse.lsp4j.services.LanguageServer; -import org.eclipse.lsp4j.services.TextDocumentService; -import org.eclipse.lsp4j.services.WorkspaceService; +import org.eclipse.lsp4j.InitializeParams; +import org.eclipse.lsp4j.InitializeResult; +import org.eclipse.lsp4j.InitializedParams; +import org.eclipse.lsp4j.services.*; import p.studio.lsp.messages.LspProjectContext; -import p.studio.lsp.services.compiler.CompilerLanguageServiceBridge; import p.studio.lsp.services.LanguageServiceBridge; +import p.studio.lsp.services.compiler.CompilerLanguageServiceBridge; import p.studio.lsp.services.protocol.mapping.Lsp4jProtocolMessageMapper; import p.studio.lsp.services.protocol.mapping.ProtocolMessageMapper; @@ -64,13 +62,13 @@ public final class PrometeuLanguageServer implements LanguageServer, LanguageCli } catch (RuntimeException runtimeException) { final LanguageClient currentClient = client; if (currentClient != null) { - currentClient.logMessage(protocolMessageMapper.mapInfoMessage( - "Failed to initialize Prometeu Studio LSP for project " + project.projectKey() + ": " + runtimeException.getMessage())); + currentClient.logMessage(protocolMessageMapper + .mapErrorMessage("Failed to initialize Prometeu Studio LSP for project " + project.projectKey() + ": " + runtimeException.getMessage())); } return CompletableFuture.failedFuture(runtimeException); } - return CompletableFuture.completedFuture(protocolMessageMapper.mapInitializeResult( - languageServiceBridge.describeServer(project))); + return CompletableFuture.completedFuture(protocolMessageMapper + .mapInitializeResult(languageServiceBridge.describeServer(project))); } @Override @@ -79,8 +77,8 @@ public final class PrometeuLanguageServer implements LanguageServer, LanguageCli if (currentClient == null) { return; } - currentClient.logMessage(protocolMessageMapper.mapInfoMessage( - "Prometeu Studio LSP connected for project " + project.projectKey())); + currentClient.logMessage(protocolMessageMapper + .mapInfoMessage("Prometeu Studio LSP connected for project " + project.projectKey())); } @Override @@ -94,8 +92,8 @@ public final class PrometeuLanguageServer implements LanguageServer, LanguageCli if (!shutdownRequested) { final LanguageClient currentClient = client; if (currentClient != null) { - currentClient.logMessage(new MessageParams(MessageType.Warning, - "Prometeu Studio LSP received exit before shutdown")); + currentClient.logMessage(protocolMessageMapper + .mapWarningMessage("Prometeu Studio LSP received exit before shutdown")); } } } diff --git a/prometeu-lsp/prometeu-lsp-v1/src/main/java/p/studio/lsp/services/protocol/mapping/Lsp4jProtocolMessageMapper.java b/prometeu-lsp/prometeu-lsp-v1/src/main/java/p/studio/lsp/services/protocol/mapping/Lsp4jProtocolMessageMapper.java index c6272e51..29079505 100644 --- a/prometeu-lsp/prometeu-lsp-v1/src/main/java/p/studio/lsp/services/protocol/mapping/Lsp4jProtocolMessageMapper.java +++ b/prometeu-lsp/prometeu-lsp-v1/src/main/java/p/studio/lsp/services/protocol/mapping/Lsp4jProtocolMessageMapper.java @@ -62,6 +62,11 @@ public final class Lsp4jProtocolMessageMapper implements ProtocolMessageMapper { return new MessageParams(MessageType.Error, message); } + @Override + public MessageParams mapWarningMessage(String message) { + return new MessageParams(MessageType.Warning, message); + } + private Diagnostic mapDiagnostic(final BaselineDocumentIssue issue) { final Diagnostic diagnostic = new Diagnostic(); diagnostic.setRange(new Range( diff --git a/prometeu-lsp/prometeu-lsp-v1/src/main/java/p/studio/lsp/services/protocol/mapping/ProtocolMessageMapper.java b/prometeu-lsp/prometeu-lsp-v1/src/main/java/p/studio/lsp/services/protocol/mapping/ProtocolMessageMapper.java index d934411e..ad69e8c0 100644 --- a/prometeu-lsp/prometeu-lsp-v1/src/main/java/p/studio/lsp/services/protocol/mapping/ProtocolMessageMapper.java +++ b/prometeu-lsp/prometeu-lsp-v1/src/main/java/p/studio/lsp/services/protocol/mapping/ProtocolMessageMapper.java @@ -19,4 +19,5 @@ public interface ProtocolMessageMapper { MessageParams mapInfoMessage(String message); MessageParams mapErrorMessage(String message); + MessageParams mapWarningMessage(String message); } diff --git a/prometeu-lsp/prometeu-lsp-v1/src/test/java/p/studio/lsp/services/compiler/CompilerLanguageServiceBridgeTest.java b/prometeu-lsp/prometeu-lsp-v1/src/test/java/p/studio/lsp/services/compiler/CompilerLanguageServiceBridgeTest.java new file mode 100644 index 00000000..1aa1be51 --- /dev/null +++ b/prometeu-lsp/prometeu-lsp-v1/src/test/java/p/studio/lsp/services/compiler/CompilerLanguageServiceBridgeTest.java @@ -0,0 +1,52 @@ +package p.studio.lsp.services.compiler; + +import org.junit.jupiter.api.Test; +import p.studio.lsp.messages.BaselineIssueSeverity; +import p.studio.lsp.messages.LspProjectContext; + +import java.nio.file.Files; +import java.nio.file.Path; + +import static org.junit.jupiter.api.Assertions.assertFalse; +import static org.junit.jupiter.api.Assertions.assertTrue; + +class CompilerLanguageServiceBridgeTest { + + @Test + void analyzeDocumentReturnsCompilerDiagnosticsForOverlayContent() { + final Path projectRoot = findRepoRoot(Path.of("").toAbsolutePath().normalize()) + .resolve("test-projects") + .resolve("main") + .toAbsolutePath() + .normalize(); + final Path documentPath = projectRoot.resolve("src").resolve("main.pbs"); + final String invalidOverlay = """ + fn frame() -> void { + let broken: int = ; + } + """; + final CompilerLanguageServiceBridge bridge = new CompilerLanguageServiceBridge(); + + final var analysis = bridge.analyzeDocument( + new LspProjectContext("main", "pbs", projectRoot), + documentPath.toUri().toString(), + invalidOverlay); + + assertFalse(analysis.issues().isEmpty(), "analyzeDocument must surface compiler diagnostics"); + assertTrue(analysis.issues().stream().anyMatch(issue -> issue.severity() == BaselineIssueSeverity.ERROR)); + assertTrue(analysis.issues().stream().anyMatch(issue -> issue.startLine() == 1)); + assertTrue(analysis.issues().stream().noneMatch(issue -> issue.message().contains("Compiler-backed baseline"))); + } + + private Path findRepoRoot(final Path start) { + var current = start; + while (current != null) { + if (Files.exists(current.resolve("settings.gradle.kts")) + && Files.exists(current.resolve("test-projects").resolve("main").resolve("prometeu.json"))) { + return current; + } + current = current.getParent(); + } + throw new IllegalStateException("unable to locate repository root from " + start); + } +} diff --git a/prometeu-lsp/prometeu-lsp-v1/src/test/java/p/studio/lsp/services/protocol/PrometeuLanguageServerTest.java b/prometeu-lsp/prometeu-lsp-v1/src/test/java/p/studio/lsp/services/protocol/PrometeuLanguageServerTest.java new file mode 100644 index 00000000..3f9dcb85 --- /dev/null +++ b/prometeu-lsp/prometeu-lsp-v1/src/test/java/p/studio/lsp/services/protocol/PrometeuLanguageServerTest.java @@ -0,0 +1,168 @@ +package p.studio.lsp.services.protocol; + +import org.eclipse.lsp4j.Hover; +import org.eclipse.lsp4j.InitializeParams; +import org.eclipse.lsp4j.InitializeResult; +import org.eclipse.lsp4j.InitializedParams; +import org.eclipse.lsp4j.MessageParams; +import org.eclipse.lsp4j.PublishDiagnosticsParams; +import org.eclipse.lsp4j.jsonrpc.ResponseErrorException; +import org.eclipse.lsp4j.services.LanguageClient; +import org.eclipse.lsp4j.services.TextDocumentService; +import org.junit.jupiter.api.Test; +import p.studio.lsp.messages.BaselineDocumentAnalysis; +import p.studio.lsp.messages.BaselineHover; +import p.studio.lsp.messages.BaselineServerDescription; +import p.studio.lsp.messages.LspProjectContext; +import p.studio.lsp.services.LanguageServiceBridge; +import p.studio.lsp.services.protocol.mapping.ProtocolMessageMapper; + +import java.nio.file.Path; +import java.util.List; +import java.util.concurrent.CompletionException; + +import static org.junit.jupiter.api.Assertions.assertEquals; +import static org.junit.jupiter.api.Assertions.assertInstanceOf; +import static org.junit.jupiter.api.Assertions.assertSame; +import static org.junit.jupiter.api.Assertions.assertTrue; + +class PrometeuLanguageServerTest { + + @Test + void initializeDelegatesThroughBridgeAndMapper() { + final RecordingBridge bridge = new RecordingBridge(); + final RecordingMapper mapper = new RecordingMapper(); + final InitializeResult expected = new InitializeResult(); + mapper.initializeResult = expected; + + final PrometeuLanguageServer server = new PrometeuLanguageServer( + new LspProjectContext("demo", "pbs", Path.of(".")), + bridge, + mapper, + new NoopTextDocumentService(), + new PrometeuWorkspaceService()); + + final InitializeParams params = new InitializeParams(); + params.setRootUri(Path.of(".").toAbsolutePath().normalize().toUri().toString()); + + final InitializeResult result = server.initialize(params).join(); + + assertSame(expected, result); + assertEquals(1, bridge.describeServerCalls); + assertSame(bridge.serverDescription, mapper.lastServerDescription); + } + + @Test + void initializeRejectsClientBoundToDifferentProjectRoot() { + final RecordingBridge bridge = new RecordingBridge(); + final RecordingMapper mapper = new RecordingMapper(); + final PrometeuLanguageServer server = new PrometeuLanguageServer( + new LspProjectContext("demo", "pbs", Path.of("/tmp/studio-project")), + bridge, + mapper, + new NoopTextDocumentService(), + new PrometeuWorkspaceService()); + + final InitializeParams params = new InitializeParams(); + params.setRootUri(Path.of("/tmp/another-project").toUri().toString()); + + final CompletionException failure = org.junit.jupiter.api.Assertions.assertThrows( + CompletionException.class, + () -> server.initialize(params).join()); + + final ResponseErrorException responseError = assertInstanceOf(ResponseErrorException.class, failure.getCause()); + assertTrue(responseError.getMessage().contains("/tmp/studio-project")); + assertEquals(0, bridge.describeServerCalls); + } + + private static final class RecordingBridge implements LanguageServiceBridge { + private int describeServerCalls; + private final BaselineServerDescription serverDescription = new BaselineServerDescription("demo", "1", true); + + @Override + public BaselineServerDescription describeServer(final LspProjectContext project) { + describeServerCalls++; + return serverDescription; + } + + @Override + public BaselineDocumentAnalysis analyzeDocument(final LspProjectContext project, final String documentUri, final String text) { + return new BaselineDocumentAnalysis(List.of()); + } + + @Override + public BaselineHover hover(final LspProjectContext project, final String documentUri, final int line, final int character) { + return new BaselineHover("hover"); + } + + @Override + public String onSave(final LspProjectContext project, final String documentUri) { + return "saved"; + } + } + + private static final class RecordingMapper implements ProtocolMessageMapper { + private InitializeResult initializeResult; + private BaselineServerDescription lastServerDescription; + + @Override + public InitializeResult mapInitializeResult(final BaselineServerDescription description) { + lastServerDescription = description; + return initializeResult; + } + + @Override + public PublishDiagnosticsParams mapDiagnostics(final String uri, final BaselineDocumentAnalysis analysis) { + throw new UnsupportedOperationException(); + } + + @Override + public PublishDiagnosticsParams emptyDiagnostics(final String uri) { + throw new UnsupportedOperationException(); + } + + @Override + public Hover mapHover(final BaselineHover hover) { + throw new UnsupportedOperationException(); + } + + @Override + public MessageParams mapInfoMessage(final String message) { + final MessageParams params = new MessageParams(); + params.setMessage(message); + return params; + } + + @Override + public MessageParams mapErrorMessage(final String message) { + final MessageParams params = new MessageParams(); + params.setMessage(message); + return params; + } + + @Override + public MessageParams mapWarningMessage(final String message) { + final MessageParams params = new MessageParams(); + params.setMessage(message); + return params; + } + } + + private static final class NoopTextDocumentService implements TextDocumentService { + @Override + public void didOpen(final org.eclipse.lsp4j.DidOpenTextDocumentParams params) { + } + + @Override + public void didChange(final org.eclipse.lsp4j.DidChangeTextDocumentParams params) { + } + + @Override + public void didClose(final org.eclipse.lsp4j.DidCloseTextDocumentParams params) { + } + + @Override + public void didSave(final org.eclipse.lsp4j.DidSaveTextDocumentParams params) { + } + } +} -- 2.47.2 From 0ac7d9e732e943eb132d4d4197313d03b36509db Mon Sep 17 00:00:00 2001 From: bQUARKz Date: Wed, 6 May 2026 04:06:09 +0100 Subject: [PATCH 14/37] adjusts on client-server connection (LSP) --- .../lsp/messages/LspServerConfiguration.java | 2 +- .../main/assets/.prometeu/cache.json | 784 +++++++++--------- tools/vscode-extension/README.md | 8 +- tools/vscode-extension/package.json | 4 +- tools/vscode-extension/src/extension.ts | 75 +- 5 files changed, 468 insertions(+), 405 deletions(-) diff --git a/prometeu-lsp/prometeu-lsp-api/src/main/java/p/studio/lsp/messages/LspServerConfiguration.java b/prometeu-lsp/prometeu-lsp-api/src/main/java/p/studio/lsp/messages/LspServerConfiguration.java index 3eb790d9..9c4344a5 100644 --- a/prometeu-lsp/prometeu-lsp-api/src/main/java/p/studio/lsp/messages/LspServerConfiguration.java +++ b/prometeu-lsp/prometeu-lsp-api/src/main/java/p/studio/lsp/messages/LspServerConfiguration.java @@ -7,7 +7,7 @@ import lombok.Getter; @Getter public class LspServerConfiguration { public static final String DEFAULT_HOST = "127.0.0.1"; - public static final int DEFAULT_PORT = 7777; + public static final int DEFAULT_PORT = 7775; @Builder.Default private final LspServerEndpoint endpoint = new LspServerEndpoint(DEFAULT_HOST, DEFAULT_PORT); diff --git a/test-projects/main/assets/.prometeu/cache.json b/test-projects/main/assets/.prometeu/cache.json index 7d30e3eb..0a8c0fad 100644 --- a/test-projects/main/assets/.prometeu/cache.json +++ b/test-projects/main/assets/.prometeu/cache.json @@ -24,14 +24,14 @@ "last_modified" : 1774359772403, "fingerprint" : "eeb7cc665386299403b7be1c272375d5077f3647c587f8033aa8c9275f840562", "metadata" : { - "palette" : { - "originalArgb8888" : [ -265674 ], - "convertedRgb565" : [ -122 ] - }, "tile" : { "width" : 32, "height" : 32, "paletteIndices" : "AQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAAAAAAAAAAABAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEAAAAAAAAAAAEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQAAAAAAAAAAAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAAAAAAAAAAABAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEAAAAAAAAAAAEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQAAAAAAAAAAAQEBAQEBAQEBAQEBAAAAAAAAAAAAAAAAAAAAAAAAAAABAQEBAQEBAQEBAQEAAAAAAAAAAAAAAAAAAAAAAAAAAAEBAQEBAQEBAQEBAQAAAAAAAAAAAAAAAAAAAAAAAAAAAQEBAQEBAQEBAQEBAAAAAAAAAAAAAAAAAAAAAAAAAAABAQEBAQEBAQEBAQEAAAAAAAAAAAAAAAAAAAAAAAAAAAEBAQEBAQEBAQEBAQAAAAAAAAAAAAAAAAAAAAAAAAAAAQEBAQEBAQEBAQEBAAAAAAAAAAAAAAAAAAAAAAAAAAABAQEBAQEBAQEBAQEAAAAAAAAAAAAAAAAAAAAAAAAAAAEBAQEBAQEBAQEBAQAAAAAAAAAAAAAAAAAAAQEBAQEBAQEBAQEBAQEBAQEBAAAAAAAAAAAAAAAAAAABAQEBAQEBAQEBAQEBAQEBAQEAAAAAAAAAAAAAAAAAAAEBAQEBAQEBAQEBAQEBAQEBAQAAAAAAAAAAAAAAAAAAAQEBAQEBAQEBAQEBAAAAAAAAAAAAAAAAAAAAAAAAAAABAQEBAQEBAQEBAQEAAAAAAAAAAAAAAAAAAAAAAAAAAAEBAQEBAQEBAQEBAQAAAAAAAAAAAAAAAAAAAQEBAQEBAQEBAQEBAQEBAQEBAAAAAAAAAAAAAAAAAAABAQEBAQEBAQEBAQEBAQEBAQEAAAAAAAAAAAAAAAAAAAEBAQEBAQEBAQEBAQEBAQEBAQAAAAAAAAAAAAAAAAAAAQEBAQEBAQEBAQEBAQEBAQEBAAAAAAAAAAAAAAAAAAABAQEBAQEBAQEBAQEBAQEBAQEAAAAAAAAAAAAAAAAAAAEBAQEBAQEBAQEBAQ==" + }, + "palette" : { + "originalArgb8888" : [ -265674 ], + "convertedRgb565" : [ -122 ] } }, "diagnostics" : [ ] @@ -42,14 +42,14 @@ "last_modified" : 1774359772405, "fingerprint" : "eeb7cc665386299403b7be1c272375d5077f3647c587f8033aa8c9275f840562", "metadata" : { - "palette" : { - "originalArgb8888" : [ -265674 ], - "convertedRgb565" : [ -122 ] - }, "tile" : { "width" : 32, "height" : 32, "paletteIndices" : "AQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAAAAAAAAAAABAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEAAAAAAAAAAAEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQAAAAAAAAAAAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAAAAAAAAAAABAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEAAAAAAAAAAAEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQAAAAAAAAAAAQEBAQEBAQEBAQEBAAAAAAAAAAAAAAAAAAAAAAAAAAABAQEBAQEBAQEBAQEAAAAAAAAAAAAAAAAAAAAAAAAAAAEBAQEBAQEBAQEBAQAAAAAAAAAAAAAAAAAAAAAAAAAAAQEBAQEBAQEBAQEBAAAAAAAAAAAAAAAAAAAAAAAAAAABAQEBAQEBAQEBAQEAAAAAAAAAAAAAAAAAAAAAAAAAAAEBAQEBAQEBAQEBAQAAAAAAAAAAAAAAAAAAAAAAAAAAAQEBAQEBAQEBAQEBAAAAAAAAAAAAAAAAAAAAAAAAAAABAQEBAQEBAQEBAQEAAAAAAAAAAAAAAAAAAAAAAAAAAAEBAQEBAQEBAQEBAQAAAAAAAAAAAAAAAAAAAQEBAQEBAQEBAQEBAQEBAQEBAAAAAAAAAAAAAAAAAAABAQEBAQEBAQEBAQEBAQEBAQEAAAAAAAAAAAAAAAAAAAEBAQEBAQEBAQEBAQEBAQEBAQAAAAAAAAAAAAAAAAAAAQEBAQEBAQEBAQEBAAAAAAAAAAAAAAAAAAAAAAAAAAABAQEBAQEBAQEBAQEAAAAAAAAAAAAAAAAAAAAAAAAAAAEBAQEBAQEBAQEBAQAAAAAAAAAAAAAAAAAAAQEBAQEBAQEBAQEBAQEBAQEBAAAAAAAAAAAAAAAAAAABAQEBAQEBAQEBAQEBAQEBAQEAAAAAAAAAAAAAAAAAAAEBAQEBAQEBAQEBAQEBAQEBAQAAAAAAAAAAAAAAAAAAAQEBAQEBAQEBAQEBAQEBAQEBAAAAAAAAAAAAAAAAAAABAQEBAQEBAQEBAQEBAQEBAQEAAAAAAAAAAAAAAAAAAAEBAQEBAQEBAQEBAQ==" + }, + "palette" : { + "originalArgb8888" : [ -265674 ], + "convertedRgb565" : [ -122 ] } }, "diagnostics" : [ ] @@ -60,14 +60,14 @@ "last_modified" : 1774359772406, "fingerprint" : "eeb7cc665386299403b7be1c272375d5077f3647c587f8033aa8c9275f840562", "metadata" : { - "palette" : { - "originalArgb8888" : [ -265674 ], - "convertedRgb565" : [ -122 ] - }, "tile" : { "width" : 32, "height" : 32, "paletteIndices" : "AQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAAAAAAAAAAABAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEAAAAAAAAAAAEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQAAAAAAAAAAAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAAAAAAAAAAABAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEAAAAAAAAAAAEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQAAAAAAAAAAAQEBAQEBAQEBAQEBAAAAAAAAAAAAAAAAAAAAAAAAAAABAQEBAQEBAQEBAQEAAAAAAAAAAAAAAAAAAAAAAAAAAAEBAQEBAQEBAQEBAQAAAAAAAAAAAAAAAAAAAAAAAAAAAQEBAQEBAQEBAQEBAAAAAAAAAAAAAAAAAAAAAAAAAAABAQEBAQEBAQEBAQEAAAAAAAAAAAAAAAAAAAAAAAAAAAEBAQEBAQEBAQEBAQAAAAAAAAAAAAAAAAAAAAAAAAAAAQEBAQEBAQEBAQEBAAAAAAAAAAAAAAAAAAAAAAAAAAABAQEBAQEBAQEBAQEAAAAAAAAAAAAAAAAAAAAAAAAAAAEBAQEBAQEBAQEBAQAAAAAAAAAAAAAAAAAAAQEBAQEBAQEBAQEBAQEBAQEBAAAAAAAAAAAAAAAAAAABAQEBAQEBAQEBAQEBAQEBAQEAAAAAAAAAAAAAAAAAAAEBAQEBAQEBAQEBAQEBAQEBAQAAAAAAAAAAAAAAAAAAAQEBAQEBAQEBAQEBAAAAAAAAAAAAAAAAAAAAAAAAAAABAQEBAQEBAQEBAQEAAAAAAAAAAAAAAAAAAAAAAAAAAAEBAQEBAQEBAQEBAQAAAAAAAAAAAAAAAAAAAQEBAQEBAQEBAQEBAQEBAQEBAAAAAAAAAAAAAAAAAAABAQEBAQEBAQEBAQEBAQEBAQEAAAAAAAAAAAAAAAAAAAEBAQEBAQEBAQEBAQEBAQEBAQAAAAAAAAAAAAAAAAAAAQEBAQEBAQEBAQEBAQEBAQEBAAAAAAAAAAAAAAAAAAABAQEBAQEBAQEBAQEBAQEBAQEAAAAAAAAAAAAAAAAAAAEBAQEBAQEBAQEBAQ==" + }, + "palette" : { + "originalArgb8888" : [ -265674 ], + "convertedRgb565" : [ -122 ] } }, "diagnostics" : [ ] @@ -78,14 +78,14 @@ "last_modified" : 1774359772408, "fingerprint" : "eeb7cc665386299403b7be1c272375d5077f3647c587f8033aa8c9275f840562", "metadata" : { - "palette" : { - "originalArgb8888" : [ -265674 ], - "convertedRgb565" : [ -122 ] - }, "tile" : { "width" : 32, "height" : 32, "paletteIndices" : "AQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAAAAAAAAAAABAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEAAAAAAAAAAAEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQAAAAAAAAAAAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAAAAAAAAAAABAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEAAAAAAAAAAAEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQAAAAAAAAAAAQEBAQEBAQEBAQEBAAAAAAAAAAAAAAAAAAAAAAAAAAABAQEBAQEBAQEBAQEAAAAAAAAAAAAAAAAAAAAAAAAAAAEBAQEBAQEBAQEBAQAAAAAAAAAAAAAAAAAAAAAAAAAAAQEBAQEBAQEBAQEBAAAAAAAAAAAAAAAAAAAAAAAAAAABAQEBAQEBAQEBAQEAAAAAAAAAAAAAAAAAAAAAAAAAAAEBAQEBAQEBAQEBAQAAAAAAAAAAAAAAAAAAAAAAAAAAAQEBAQEBAQEBAQEBAAAAAAAAAAAAAAAAAAAAAAAAAAABAQEBAQEBAQEBAQEAAAAAAAAAAAAAAAAAAAAAAAAAAAEBAQEBAQEBAQEBAQAAAAAAAAAAAAAAAAAAAQEBAQEBAQEBAQEBAQEBAQEBAAAAAAAAAAAAAAAAAAABAQEBAQEBAQEBAQEBAQEBAQEAAAAAAAAAAAAAAAAAAAEBAQEBAQEBAQEBAQEBAQEBAQAAAAAAAAAAAAAAAAAAAQEBAQEBAQEBAQEBAAAAAAAAAAAAAAAAAAAAAAAAAAABAQEBAQEBAQEBAQEAAAAAAAAAAAAAAAAAAAAAAAAAAAEBAQEBAQEBAQEBAQAAAAAAAAAAAAAAAAAAAQEBAQEBAQEBAQEBAQEBAQEBAAAAAAAAAAAAAAAAAAABAQEBAQEBAQEBAQEBAQEBAQEAAAAAAAAAAAAAAAAAAAEBAQEBAQEBAQEBAQEBAQEBAQAAAAAAAAAAAAAAAAAAAQEBAQEBAQEBAQEBAQEBAQEBAAAAAAAAAAAAAAAAAAABAQEBAQEBAQEBAQEBAQEBAQEAAAAAAAAAAAAAAAAAAAEBAQEBAQEBAQEBAQ==" + }, + "palette" : { + "originalArgb8888" : [ -265674 ], + "convertedRgb565" : [ -122 ] } }, "diagnostics" : [ ] @@ -96,14 +96,14 @@ "last_modified" : 1774359772409, "fingerprint" : "eeb7cc665386299403b7be1c272375d5077f3647c587f8033aa8c9275f840562", "metadata" : { - "palette" : { - "originalArgb8888" : [ -265674 ], - "convertedRgb565" : [ -122 ] - }, "tile" : { "width" : 32, "height" : 32, "paletteIndices" : "AQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAAAAAAAAAAABAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEAAAAAAAAAAAEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQAAAAAAAAAAAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAAAAAAAAAAABAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEAAAAAAAAAAAEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQAAAAAAAAAAAQEBAQEBAQEBAQEBAAAAAAAAAAAAAAAAAAAAAAAAAAABAQEBAQEBAQEBAQEAAAAAAAAAAAAAAAAAAAAAAAAAAAEBAQEBAQEBAQEBAQAAAAAAAAAAAAAAAAAAAAAAAAAAAQEBAQEBAQEBAQEBAAAAAAAAAAAAAAAAAAAAAAAAAAABAQEBAQEBAQEBAQEAAAAAAAAAAAAAAAAAAAAAAAAAAAEBAQEBAQEBAQEBAQAAAAAAAAAAAAAAAAAAAAAAAAAAAQEBAQEBAQEBAQEBAAAAAAAAAAAAAAAAAAAAAAAAAAABAQEBAQEBAQEBAQEAAAAAAAAAAAAAAAAAAAAAAAAAAAEBAQEBAQEBAQEBAQAAAAAAAAAAAAAAAAAAAQEBAQEBAQEBAQEBAQEBAQEBAAAAAAAAAAAAAAAAAAABAQEBAQEBAQEBAQEBAQEBAQEAAAAAAAAAAAAAAAAAAAEBAQEBAQEBAQEBAQEBAQEBAQAAAAAAAAAAAAAAAAAAAQEBAQEBAQEBAQEBAAAAAAAAAAAAAAAAAAAAAAAAAAABAQEBAQEBAQEBAQEAAAAAAAAAAAAAAAAAAAAAAAAAAAEBAQEBAQEBAQEBAQAAAAAAAAAAAAAAAAAAAQEBAQEBAQEBAQEBAQEBAQEBAAAAAAAAAAAAAAAAAAABAQEBAQEBAQEBAQEBAQEBAQEAAAAAAAAAAAAAAAAAAAEBAQEBAQEBAQEBAQEBAQEBAQAAAAAAAAAAAAAAAAAAAQEBAQEBAQEBAQEBAQEBAQEBAAAAAAAAAAAAAAAAAAABAQEBAQEBAQEBAQEBAQEBAQEAAAAAAAAAAAAAAAAAAAEBAQEBAQEBAQEBAQ==" + }, + "palette" : { + "originalArgb8888" : [ -265674 ], + "convertedRgb565" : [ -122 ] } }, "diagnostics" : [ ] @@ -114,14 +114,14 @@ "last_modified" : 1774359772411, "fingerprint" : "eeb7cc665386299403b7be1c272375d5077f3647c587f8033aa8c9275f840562", "metadata" : { - "palette" : { - "originalArgb8888" : [ -265674 ], - "convertedRgb565" : [ -122 ] - }, "tile" : { "width" : 32, "height" : 32, "paletteIndices" : "AQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAAAAAAAAAAABAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEAAAAAAAAAAAEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQAAAAAAAAAAAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAAAAAAAAAAABAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEAAAAAAAAAAAEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQAAAAAAAAAAAQEBAQEBAQEBAQEBAAAAAAAAAAAAAAAAAAAAAAAAAAABAQEBAQEBAQEBAQEAAAAAAAAAAAAAAAAAAAAAAAAAAAEBAQEBAQEBAQEBAQAAAAAAAAAAAAAAAAAAAAAAAAAAAQEBAQEBAQEBAQEBAAAAAAAAAAAAAAAAAAAAAAAAAAABAQEBAQEBAQEBAQEAAAAAAAAAAAAAAAAAAAAAAAAAAAEBAQEBAQEBAQEBAQAAAAAAAAAAAAAAAAAAAAAAAAAAAQEBAQEBAQEBAQEBAAAAAAAAAAAAAAAAAAAAAAAAAAABAQEBAQEBAQEBAQEAAAAAAAAAAAAAAAAAAAAAAAAAAAEBAQEBAQEBAQEBAQAAAAAAAAAAAAAAAAAAAQEBAQEBAQEBAQEBAQEBAQEBAAAAAAAAAAAAAAAAAAABAQEBAQEBAQEBAQEBAQEBAQEAAAAAAAAAAAAAAAAAAAEBAQEBAQEBAQEBAQEBAQEBAQAAAAAAAAAAAAAAAAAAAQEBAQEBAQEBAQEBAAAAAAAAAAAAAAAAAAAAAAAAAAABAQEBAQEBAQEBAQEAAAAAAAAAAAAAAAAAAAAAAAAAAAEBAQEBAQEBAQEBAQAAAAAAAAAAAAAAAAAAAQEBAQEBAQEBAQEBAQEBAQEBAAAAAAAAAAAAAAAAAAABAQEBAQEBAQEBAQEBAQEBAQEAAAAAAAAAAAAAAAAAAAEBAQEBAQEBAQEBAQEBAQEBAQAAAAAAAAAAAAAAAAAAAQEBAQEBAQEBAQEBAQEBAQEBAAAAAAAAAAAAAAAAAAABAQEBAQEBAQEBAQEBAQEBAQEAAAAAAAAAAAAAAAAAAAEBAQEBAQEBAQEBAQ==" + }, + "palette" : { + "originalArgb8888" : [ -265674 ], + "convertedRgb565" : [ -122 ] } }, "diagnostics" : [ ] @@ -132,14 +132,14 @@ "last_modified" : 1774359772412, "fingerprint" : "eeb7cc665386299403b7be1c272375d5077f3647c587f8033aa8c9275f840562", "metadata" : { - "palette" : { - "originalArgb8888" : [ -265674 ], - "convertedRgb565" : [ -122 ] - }, "tile" : { "width" : 32, "height" : 32, "paletteIndices" : "AQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAAAAAAAAAAABAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEAAAAAAAAAAAEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQAAAAAAAAAAAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAAAAAAAAAAABAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEAAAAAAAAAAAEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQAAAAAAAAAAAQEBAQEBAQEBAQEBAAAAAAAAAAAAAAAAAAAAAAAAAAABAQEBAQEBAQEBAQEAAAAAAAAAAAAAAAAAAAAAAAAAAAEBAQEBAQEBAQEBAQAAAAAAAAAAAAAAAAAAAAAAAAAAAQEBAQEBAQEBAQEBAAAAAAAAAAAAAAAAAAAAAAAAAAABAQEBAQEBAQEBAQEAAAAAAAAAAAAAAAAAAAAAAAAAAAEBAQEBAQEBAQEBAQAAAAAAAAAAAAAAAAAAAAAAAAAAAQEBAQEBAQEBAQEBAAAAAAAAAAAAAAAAAAAAAAAAAAABAQEBAQEBAQEBAQEAAAAAAAAAAAAAAAAAAAAAAAAAAAEBAQEBAQEBAQEBAQAAAAAAAAAAAAAAAAAAAQEBAQEBAQEBAQEBAQEBAQEBAAAAAAAAAAAAAAAAAAABAQEBAQEBAQEBAQEBAQEBAQEAAAAAAAAAAAAAAAAAAAEBAQEBAQEBAQEBAQEBAQEBAQAAAAAAAAAAAAAAAAAAAQEBAQEBAQEBAQEBAAAAAAAAAAAAAAAAAAAAAAAAAAABAQEBAQEBAQEBAQEAAAAAAAAAAAAAAAAAAAAAAAAAAAEBAQEBAQEBAQEBAQAAAAAAAAAAAAAAAAAAAQEBAQEBAQEBAQEBAQEBAQEBAAAAAAAAAAAAAAAAAAABAQEBAQEBAQEBAQEBAQEBAQEAAAAAAAAAAAAAAAAAAAEBAQEBAQEBAQEBAQEBAQEBAQAAAAAAAAAAAAAAAAAAAQEBAQEBAQEBAQEBAQEBAQEBAAAAAAAAAAAAAAAAAAABAQEBAQEBAQEBAQEBAQEBAQEAAAAAAAAAAAAAAAAAAAEBAQEBAQEBAQEBAQ==" + }, + "palette" : { + "originalArgb8888" : [ -265674 ], + "convertedRgb565" : [ -122 ] } }, "diagnostics" : [ ] @@ -150,14 +150,14 @@ "last_modified" : 1774359772413, "fingerprint" : "eeb7cc665386299403b7be1c272375d5077f3647c587f8033aa8c9275f840562", "metadata" : { - "palette" : { - "originalArgb8888" : [ -265674 ], - "convertedRgb565" : [ -122 ] - }, "tile" : { "width" : 32, "height" : 32, "paletteIndices" : "AQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAAAAAAAAAAABAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEAAAAAAAAAAAEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQAAAAAAAAAAAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAAAAAAAAAAABAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEAAAAAAAAAAAEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQAAAAAAAAAAAQEBAQEBAQEBAQEBAAAAAAAAAAAAAAAAAAAAAAAAAAABAQEBAQEBAQEBAQEAAAAAAAAAAAAAAAAAAAAAAAAAAAEBAQEBAQEBAQEBAQAAAAAAAAAAAAAAAAAAAAAAAAAAAQEBAQEBAQEBAQEBAAAAAAAAAAAAAAAAAAAAAAAAAAABAQEBAQEBAQEBAQEAAAAAAAAAAAAAAAAAAAAAAAAAAAEBAQEBAQEBAQEBAQAAAAAAAAAAAAAAAAAAAAAAAAAAAQEBAQEBAQEBAQEBAAAAAAAAAAAAAAAAAAAAAAAAAAABAQEBAQEBAQEBAQEAAAAAAAAAAAAAAAAAAAAAAAAAAAEBAQEBAQEBAQEBAQAAAAAAAAAAAAAAAAAAAQEBAQEBAQEBAQEBAQEBAQEBAAAAAAAAAAAAAAAAAAABAQEBAQEBAQEBAQEBAQEBAQEAAAAAAAAAAAAAAAAAAAEBAQEBAQEBAQEBAQEBAQEBAQAAAAAAAAAAAAAAAAAAAQEBAQEBAQEBAQEBAAAAAAAAAAAAAAAAAAAAAAAAAAABAQEBAQEBAQEBAQEAAAAAAAAAAAAAAAAAAAAAAAAAAAEBAQEBAQEBAQEBAQAAAAAAAAAAAAAAAAAAAQEBAQEBAQEBAQEBAQEBAQEBAAAAAAAAAAAAAAAAAAABAQEBAQEBAQEBAQEBAQEBAQEAAAAAAAAAAAAAAAAAAAEBAQEBAQEBAQEBAQEBAQEBAQAAAAAAAAAAAAAAAAAAAQEBAQEBAQEBAQEBAQEBAQEBAAAAAAAAAAAAAAAAAAABAQEBAQEBAQEBAQEBAQEBAQEAAAAAAAAAAAAAAAAAAAEBAQEBAQEBAQEBAQ==" + }, + "palette" : { + "originalArgb8888" : [ -265674 ], + "convertedRgb565" : [ -122 ] } }, "diagnostics" : [ ] @@ -168,14 +168,14 @@ "last_modified" : 1774359772415, "fingerprint" : "eeb7cc665386299403b7be1c272375d5077f3647c587f8033aa8c9275f840562", "metadata" : { - "palette" : { - "originalArgb8888" : [ -265674 ], - "convertedRgb565" : [ -122 ] - }, "tile" : { "width" : 32, "height" : 32, "paletteIndices" : "AQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAAAAAAAAAAABAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEAAAAAAAAAAAEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQAAAAAAAAAAAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAAAAAAAAAAABAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEAAAAAAAAAAAEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQAAAAAAAAAAAQEBAQEBAQEBAQEBAAAAAAAAAAAAAAAAAAAAAAAAAAABAQEBAQEBAQEBAQEAAAAAAAAAAAAAAAAAAAAAAAAAAAEBAQEBAQEBAQEBAQAAAAAAAAAAAAAAAAAAAAAAAAAAAQEBAQEBAQEBAQEBAAAAAAAAAAAAAAAAAAAAAAAAAAABAQEBAQEBAQEBAQEAAAAAAAAAAAAAAAAAAAAAAAAAAAEBAQEBAQEBAQEBAQAAAAAAAAAAAAAAAAAAAAAAAAAAAQEBAQEBAQEBAQEBAAAAAAAAAAAAAAAAAAAAAAAAAAABAQEBAQEBAQEBAQEAAAAAAAAAAAAAAAAAAAAAAAAAAAEBAQEBAQEBAQEBAQAAAAAAAAAAAAAAAAAAAQEBAQEBAQEBAQEBAQEBAQEBAAAAAAAAAAAAAAAAAAABAQEBAQEBAQEBAQEBAQEBAQEAAAAAAAAAAAAAAAAAAAEBAQEBAQEBAQEBAQEBAQEBAQAAAAAAAAAAAAAAAAAAAQEBAQEBAQEBAQEBAAAAAAAAAAAAAAAAAAAAAAAAAAABAQEBAQEBAQEBAQEAAAAAAAAAAAAAAAAAAAAAAAAAAAEBAQEBAQEBAQEBAQAAAAAAAAAAAAAAAAAAAQEBAQEBAQEBAQEBAQEBAQEBAAAAAAAAAAAAAAAAAAABAQEBAQEBAQEBAQEBAQEBAQEAAAAAAAAAAAAAAAAAAAEBAQEBAQEBAQEBAQEBAQEBAQAAAAAAAAAAAAAAAAAAAQEBAQEBAQEBAQEBAQEBAQEBAAAAAAAAAAAAAAAAAAABAQEBAQEBAQEBAQEBAQEBAQEAAAAAAAAAAAAAAAAAAAEBAQEBAQEBAQEBAQ==" + }, + "palette" : { + "originalArgb8888" : [ -265674 ], + "convertedRgb565" : [ -122 ] } }, "diagnostics" : [ ] @@ -186,14 +186,14 @@ "last_modified" : 1774359772416, "fingerprint" : "eeb7cc665386299403b7be1c272375d5077f3647c587f8033aa8c9275f840562", "metadata" : { - "palette" : { - "originalArgb8888" : [ -265674 ], - "convertedRgb565" : [ -122 ] - }, "tile" : { "width" : 32, "height" : 32, "paletteIndices" : "AQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAAAAAAAAAAABAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEAAAAAAAAAAAEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQAAAAAAAAAAAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAAAAAAAAAAABAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEAAAAAAAAAAAEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQAAAAAAAAAAAQEBAQEBAQEBAQEBAAAAAAAAAAAAAAAAAAAAAAAAAAABAQEBAQEBAQEBAQEAAAAAAAAAAAAAAAAAAAAAAAAAAAEBAQEBAQEBAQEBAQAAAAAAAAAAAAAAAAAAAAAAAAAAAQEBAQEBAQEBAQEBAAAAAAAAAAAAAAAAAAAAAAAAAAABAQEBAQEBAQEBAQEAAAAAAAAAAAAAAAAAAAAAAAAAAAEBAQEBAQEBAQEBAQAAAAAAAAAAAAAAAAAAAAAAAAAAAQEBAQEBAQEBAQEBAAAAAAAAAAAAAAAAAAAAAAAAAAABAQEBAQEBAQEBAQEAAAAAAAAAAAAAAAAAAAAAAAAAAAEBAQEBAQEBAQEBAQAAAAAAAAAAAAAAAAAAAQEBAQEBAQEBAQEBAQEBAQEBAAAAAAAAAAAAAAAAAAABAQEBAQEBAQEBAQEBAQEBAQEAAAAAAAAAAAAAAAAAAAEBAQEBAQEBAQEBAQEBAQEBAQAAAAAAAAAAAAAAAAAAAQEBAQEBAQEBAQEBAAAAAAAAAAAAAAAAAAAAAAAAAAABAQEBAQEBAQEBAQEAAAAAAAAAAAAAAAAAAAAAAAAAAAEBAQEBAQEBAQEBAQAAAAAAAAAAAAAAAAAAAQEBAQEBAQEBAQEBAQEBAQEBAAAAAAAAAAAAAAAAAAABAQEBAQEBAQEBAQEBAQEBAQEAAAAAAAAAAAAAAAAAAAEBAQEBAQEBAQEBAQEBAQEBAQAAAAAAAAAAAAAAAAAAAQEBAQEBAQEBAQEBAQEBAQEBAAAAAAAAAAAAAAAAAAABAQEBAQEBAQEBAQEBAQEBAQEAAAAAAAAAAAAAAAAAAAEBAQEBAQEBAQEBAQ==" + }, + "palette" : { + "originalArgb8888" : [ -265674 ], + "convertedRgb565" : [ -122 ] } }, "diagnostics" : [ ] @@ -204,14 +204,14 @@ "last_modified" : 1774359772417, "fingerprint" : "eeb7cc665386299403b7be1c272375d5077f3647c587f8033aa8c9275f840562", "metadata" : { - "palette" : { - "originalArgb8888" : [ -265674 ], - "convertedRgb565" : [ -122 ] - }, "tile" : { "width" : 32, "height" : 32, "paletteIndices" : "AQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAAAAAAAAAAABAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEAAAAAAAAAAAEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQAAAAAAAAAAAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAAAAAAAAAAABAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEAAAAAAAAAAAEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQAAAAAAAAAAAQEBAQEBAQEBAQEBAAAAAAAAAAAAAAAAAAAAAAAAAAABAQEBAQEBAQEBAQEAAAAAAAAAAAAAAAAAAAAAAAAAAAEBAQEBAQEBAQEBAQAAAAAAAAAAAAAAAAAAAAAAAAAAAQEBAQEBAQEBAQEBAAAAAAAAAAAAAAAAAAAAAAAAAAABAQEBAQEBAQEBAQEAAAAAAAAAAAAAAAAAAAAAAAAAAAEBAQEBAQEBAQEBAQAAAAAAAAAAAAAAAAAAAAAAAAAAAQEBAQEBAQEBAQEBAAAAAAAAAAAAAAAAAAAAAAAAAAABAQEBAQEBAQEBAQEAAAAAAAAAAAAAAAAAAAAAAAAAAAEBAQEBAQEBAQEBAQAAAAAAAAAAAAAAAAAAAQEBAQEBAQEBAQEBAQEBAQEBAAAAAAAAAAAAAAAAAAABAQEBAQEBAQEBAQEBAQEBAQEAAAAAAAAAAAAAAAAAAAEBAQEBAQEBAQEBAQEBAQEBAQAAAAAAAAAAAAAAAAAAAQEBAQEBAQEBAQEBAAAAAAAAAAAAAAAAAAAAAAAAAAABAQEBAQEBAQEBAQEAAAAAAAAAAAAAAAAAAAAAAAAAAAEBAQEBAQEBAQEBAQAAAAAAAAAAAAAAAAAAAQEBAQEBAQEBAQEBAQEBAQEBAAAAAAAAAAAAAAAAAAABAQEBAQEBAQEBAQEBAQEBAQEAAAAAAAAAAAAAAAAAAAEBAQEBAQEBAQEBAQEBAQEBAQAAAAAAAAAAAAAAAAAAAQEBAQEBAQEBAQEBAQEBAQEBAAAAAAAAAAAAAAAAAAABAQEBAQEBAQEBAQEBAQEBAQEAAAAAAAAAAAAAAAAAAAEBAQEBAQEBAQEBAQ==" + }, + "palette" : { + "originalArgb8888" : [ -265674 ], + "convertedRgb565" : [ -122 ] } }, "diagnostics" : [ ] @@ -222,14 +222,14 @@ "last_modified" : 1774359772418, "fingerprint" : "eeb7cc665386299403b7be1c272375d5077f3647c587f8033aa8c9275f840562", "metadata" : { - "palette" : { - "originalArgb8888" : [ -265674 ], - "convertedRgb565" : [ -122 ] - }, "tile" : { "width" : 32, "height" : 32, "paletteIndices" : "AQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAAAAAAAAAAABAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEAAAAAAAAAAAEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQAAAAAAAAAAAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAAAAAAAAAAABAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEAAAAAAAAAAAEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQAAAAAAAAAAAQEBAQEBAQEBAQEBAAAAAAAAAAAAAAAAAAAAAAAAAAABAQEBAQEBAQEBAQEAAAAAAAAAAAAAAAAAAAAAAAAAAAEBAQEBAQEBAQEBAQAAAAAAAAAAAAAAAAAAAAAAAAAAAQEBAQEBAQEBAQEBAAAAAAAAAAAAAAAAAAAAAAAAAAABAQEBAQEBAQEBAQEAAAAAAAAAAAAAAAAAAAAAAAAAAAEBAQEBAQEBAQEBAQAAAAAAAAAAAAAAAAAAAAAAAAAAAQEBAQEBAQEBAQEBAAAAAAAAAAAAAAAAAAAAAAAAAAABAQEBAQEBAQEBAQEAAAAAAAAAAAAAAAAAAAAAAAAAAAEBAQEBAQEBAQEBAQAAAAAAAAAAAAAAAAAAAQEBAQEBAQEBAQEBAQEBAQEBAAAAAAAAAAAAAAAAAAABAQEBAQEBAQEBAQEBAQEBAQEAAAAAAAAAAAAAAAAAAAEBAQEBAQEBAQEBAQEBAQEBAQAAAAAAAAAAAAAAAAAAAQEBAQEBAQEBAQEBAAAAAAAAAAAAAAAAAAAAAAAAAAABAQEBAQEBAQEBAQEAAAAAAAAAAAAAAAAAAAAAAAAAAAEBAQEBAQEBAQEBAQAAAAAAAAAAAAAAAAAAAQEBAQEBAQEBAQEBAQEBAQEBAAAAAAAAAAAAAAAAAAABAQEBAQEBAQEBAQEBAQEBAQEAAAAAAAAAAAAAAAAAAAEBAQEBAQEBAQEBAQEBAQEBAQAAAAAAAAAAAAAAAAAAAQEBAQEBAQEBAQEBAQEBAQEBAAAAAAAAAAAAAAAAAAABAQEBAQEBAQEBAQEBAQEBAQEAAAAAAAAAAAAAAAAAAAEBAQEBAQEBAQEBAQ==" + }, + "palette" : { + "originalArgb8888" : [ -265674 ], + "convertedRgb565" : [ -122 ] } }, "diagnostics" : [ ] @@ -240,14 +240,14 @@ "last_modified" : 1774359772420, "fingerprint" : "eeb7cc665386299403b7be1c272375d5077f3647c587f8033aa8c9275f840562", "metadata" : { - "palette" : { - "originalArgb8888" : [ -265674 ], - "convertedRgb565" : [ -122 ] - }, "tile" : { "width" : 32, "height" : 32, "paletteIndices" : "AQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAAAAAAAAAAABAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEAAAAAAAAAAAEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQAAAAAAAAAAAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAAAAAAAAAAABAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEAAAAAAAAAAAEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQAAAAAAAAAAAQEBAQEBAQEBAQEBAAAAAAAAAAAAAAAAAAAAAAAAAAABAQEBAQEBAQEBAQEAAAAAAAAAAAAAAAAAAAAAAAAAAAEBAQEBAQEBAQEBAQAAAAAAAAAAAAAAAAAAAAAAAAAAAQEBAQEBAQEBAQEBAAAAAAAAAAAAAAAAAAAAAAAAAAABAQEBAQEBAQEBAQEAAAAAAAAAAAAAAAAAAAAAAAAAAAEBAQEBAQEBAQEBAQAAAAAAAAAAAAAAAAAAAAAAAAAAAQEBAQEBAQEBAQEBAAAAAAAAAAAAAAAAAAAAAAAAAAABAQEBAQEBAQEBAQEAAAAAAAAAAAAAAAAAAAAAAAAAAAEBAQEBAQEBAQEBAQAAAAAAAAAAAAAAAAAAAQEBAQEBAQEBAQEBAQEBAQEBAAAAAAAAAAAAAAAAAAABAQEBAQEBAQEBAQEBAQEBAQEAAAAAAAAAAAAAAAAAAAEBAQEBAQEBAQEBAQEBAQEBAQAAAAAAAAAAAAAAAAAAAQEBAQEBAQEBAQEBAAAAAAAAAAAAAAAAAAAAAAAAAAABAQEBAQEBAQEBAQEAAAAAAAAAAAAAAAAAAAAAAAAAAAEBAQEBAQEBAQEBAQAAAAAAAAAAAAAAAAAAAQEBAQEBAQEBAQEBAQEBAQEBAAAAAAAAAAAAAAAAAAABAQEBAQEBAQEBAQEBAQEBAQEAAAAAAAAAAAAAAAAAAAEBAQEBAQEBAQEBAQEBAQEBAQAAAAAAAAAAAAAAAAAAAQEBAQEBAQEBAQEBAQEBAQEBAAAAAAAAAAAAAAAAAAABAQEBAQEBAQEBAQEBAQEBAQEAAAAAAAAAAAAAAAAAAAEBAQEBAQEBAQEBAQ==" + }, + "palette" : { + "originalArgb8888" : [ -265674 ], + "convertedRgb565" : [ -122 ] } }, "diagnostics" : [ ] @@ -258,14 +258,14 @@ "last_modified" : 1774359772421, "fingerprint" : "eeb7cc665386299403b7be1c272375d5077f3647c587f8033aa8c9275f840562", "metadata" : { - "palette" : { - "originalArgb8888" : [ -265674 ], - "convertedRgb565" : [ -122 ] - }, "tile" : { "width" : 32, "height" : 32, "paletteIndices" : "AQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAAAAAAAAAAABAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEAAAAAAAAAAAEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQAAAAAAAAAAAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAAAAAAAAAAABAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEAAAAAAAAAAAEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQAAAAAAAAAAAQEBAQEBAQEBAQEBAAAAAAAAAAAAAAAAAAAAAAAAAAABAQEBAQEBAQEBAQEAAAAAAAAAAAAAAAAAAAAAAAAAAAEBAQEBAQEBAQEBAQAAAAAAAAAAAAAAAAAAAAAAAAAAAQEBAQEBAQEBAQEBAAAAAAAAAAAAAAAAAAAAAAAAAAABAQEBAQEBAQEBAQEAAAAAAAAAAAAAAAAAAAAAAAAAAAEBAQEBAQEBAQEBAQAAAAAAAAAAAAAAAAAAAAAAAAAAAQEBAQEBAQEBAQEBAAAAAAAAAAAAAAAAAAAAAAAAAAABAQEBAQEBAQEBAQEAAAAAAAAAAAAAAAAAAAAAAAAAAAEBAQEBAQEBAQEBAQAAAAAAAAAAAAAAAAAAAQEBAQEBAQEBAQEBAQEBAQEBAAAAAAAAAAAAAAAAAAABAQEBAQEBAQEBAQEBAQEBAQEAAAAAAAAAAAAAAAAAAAEBAQEBAQEBAQEBAQEBAQEBAQAAAAAAAAAAAAAAAAAAAQEBAQEBAQEBAQEBAAAAAAAAAAAAAAAAAAAAAAAAAAABAQEBAQEBAQEBAQEAAAAAAAAAAAAAAAAAAAAAAAAAAAEBAQEBAQEBAQEBAQAAAAAAAAAAAAAAAAAAAQEBAQEBAQEBAQEBAQEBAQEBAAAAAAAAAAAAAAAAAAABAQEBAQEBAQEBAQEBAQEBAQEAAAAAAAAAAAAAAAAAAAEBAQEBAQEBAQEBAQEBAQEBAQAAAAAAAAAAAAAAAAAAAQEBAQEBAQEBAQEBAQEBAQEBAAAAAAAAAAAAAAAAAAABAQEBAQEBAQEBAQEBAQEBAQEAAAAAAAAAAAAAAAAAAAEBAQEBAQEBAQEBAQ==" + }, + "palette" : { + "originalArgb8888" : [ -265674 ], + "convertedRgb565" : [ -122 ] } }, "diagnostics" : [ ] @@ -276,14 +276,14 @@ "last_modified" : 1774359772423, "fingerprint" : "eeb7cc665386299403b7be1c272375d5077f3647c587f8033aa8c9275f840562", "metadata" : { - "palette" : { - "originalArgb8888" : [ -265674 ], - "convertedRgb565" : [ -122 ] - }, "tile" : { "width" : 32, "height" : 32, "paletteIndices" : "AQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAAAAAAAAAAABAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEAAAAAAAAAAAEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQAAAAAAAAAAAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAAAAAAAAAAABAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEAAAAAAAAAAAEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQAAAAAAAAAAAQEBAQEBAQEBAQEBAAAAAAAAAAAAAAAAAAAAAAAAAAABAQEBAQEBAQEBAQEAAAAAAAAAAAAAAAAAAAAAAAAAAAEBAQEBAQEBAQEBAQAAAAAAAAAAAAAAAAAAAAAAAAAAAQEBAQEBAQEBAQEBAAAAAAAAAAAAAAAAAAAAAAAAAAABAQEBAQEBAQEBAQEAAAAAAAAAAAAAAAAAAAAAAAAAAAEBAQEBAQEBAQEBAQAAAAAAAAAAAAAAAAAAAAAAAAAAAQEBAQEBAQEBAQEBAAAAAAAAAAAAAAAAAAAAAAAAAAABAQEBAQEBAQEBAQEAAAAAAAAAAAAAAAAAAAAAAAAAAAEBAQEBAQEBAQEBAQAAAAAAAAAAAAAAAAAAAQEBAQEBAQEBAQEBAQEBAQEBAAAAAAAAAAAAAAAAAAABAQEBAQEBAQEBAQEBAQEBAQEAAAAAAAAAAAAAAAAAAAEBAQEBAQEBAQEBAQEBAQEBAQAAAAAAAAAAAAAAAAAAAQEBAQEBAQEBAQEBAAAAAAAAAAAAAAAAAAAAAAAAAAABAQEBAQEBAQEBAQEAAAAAAAAAAAAAAAAAAAAAAAAAAAEBAQEBAQEBAQEBAQAAAAAAAAAAAAAAAAAAAQEBAQEBAQEBAQEBAQEBAQEBAAAAAAAAAAAAAAAAAAABAQEBAQEBAQEBAQEBAQEBAQEAAAAAAAAAAAAAAAAAAAEBAQEBAQEBAQEBAQEBAQEBAQAAAAAAAAAAAAAAAAAAAQEBAQEBAQEBAQEBAQEBAQEBAAAAAAAAAAAAAAAAAAABAQEBAQEBAQEBAQEBAQEBAQEAAAAAAAAAAAAAAAAAAAEBAQEBAQEBAQEBAQ==" + }, + "palette" : { + "originalArgb8888" : [ -265674 ], + "convertedRgb565" : [ -122 ] } }, "diagnostics" : [ ] @@ -294,14 +294,14 @@ "last_modified" : 1774359772424, "fingerprint" : "eeb7cc665386299403b7be1c272375d5077f3647c587f8033aa8c9275f840562", "metadata" : { - "palette" : { - "originalArgb8888" : [ -265674 ], - "convertedRgb565" : [ -122 ] - }, "tile" : { "width" : 32, "height" : 32, "paletteIndices" : "AQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAAAAAAAAAAABAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEAAAAAAAAAAAEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQAAAAAAAAAAAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAAAAAAAAAAABAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEAAAAAAAAAAAEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQAAAAAAAAAAAQEBAQEBAQEBAQEBAAAAAAAAAAAAAAAAAAAAAAAAAAABAQEBAQEBAQEBAQEAAAAAAAAAAAAAAAAAAAAAAAAAAAEBAQEBAQEBAQEBAQAAAAAAAAAAAAAAAAAAAAAAAAAAAQEBAQEBAQEBAQEBAAAAAAAAAAAAAAAAAAAAAAAAAAABAQEBAQEBAQEBAQEAAAAAAAAAAAAAAAAAAAAAAAAAAAEBAQEBAQEBAQEBAQAAAAAAAAAAAAAAAAAAAAAAAAAAAQEBAQEBAQEBAQEBAAAAAAAAAAAAAAAAAAAAAAAAAAABAQEBAQEBAQEBAQEAAAAAAAAAAAAAAAAAAAAAAAAAAAEBAQEBAQEBAQEBAQAAAAAAAAAAAAAAAAAAAQEBAQEBAQEBAQEBAQEBAQEBAAAAAAAAAAAAAAAAAAABAQEBAQEBAQEBAQEBAQEBAQEAAAAAAAAAAAAAAAAAAAEBAQEBAQEBAQEBAQEBAQEBAQAAAAAAAAAAAAAAAAAAAQEBAQEBAQEBAQEBAAAAAAAAAAAAAAAAAAAAAAAAAAABAQEBAQEBAQEBAQEAAAAAAAAAAAAAAAAAAAAAAAAAAAEBAQEBAQEBAQEBAQAAAAAAAAAAAAAAAAAAAQEBAQEBAQEBAQEBAQEBAQEBAAAAAAAAAAAAAAAAAAABAQEBAQEBAQEBAQEBAQEBAQEAAAAAAAAAAAAAAAAAAAEBAQEBAQEBAQEBAQEBAQEBAQAAAAAAAAAAAAAAAAAAAQEBAQEBAQEBAQEBAQEBAQEBAAAAAAAAAAAAAAAAAAABAQEBAQEBAQEBAQEBAQEBAQEAAAAAAAAAAAAAAAAAAAEBAQEBAQEBAQEBAQ==" + }, + "palette" : { + "originalArgb8888" : [ -265674 ], + "convertedRgb565" : [ -122 ] } }, "diagnostics" : [ ] @@ -312,14 +312,14 @@ "last_modified" : 1774359772425, "fingerprint" : "eeb7cc665386299403b7be1c272375d5077f3647c587f8033aa8c9275f840562", "metadata" : { - "palette" : { - "originalArgb8888" : [ -265674 ], - "convertedRgb565" : [ -122 ] - }, "tile" : { "width" : 32, "height" : 32, "paletteIndices" : "AQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAAAAAAAAAAABAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEAAAAAAAAAAAEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQAAAAAAAAAAAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAAAAAAAAAAABAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEAAAAAAAAAAAEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQAAAAAAAAAAAQEBAQEBAQEBAQEBAAAAAAAAAAAAAAAAAAAAAAAAAAABAQEBAQEBAQEBAQEAAAAAAAAAAAAAAAAAAAAAAAAAAAEBAQEBAQEBAQEBAQAAAAAAAAAAAAAAAAAAAAAAAAAAAQEBAQEBAQEBAQEBAAAAAAAAAAAAAAAAAAAAAAAAAAABAQEBAQEBAQEBAQEAAAAAAAAAAAAAAAAAAAAAAAAAAAEBAQEBAQEBAQEBAQAAAAAAAAAAAAAAAAAAAAAAAAAAAQEBAQEBAQEBAQEBAAAAAAAAAAAAAAAAAAAAAAAAAAABAQEBAQEBAQEBAQEAAAAAAAAAAAAAAAAAAAAAAAAAAAEBAQEBAQEBAQEBAQAAAAAAAAAAAAAAAAAAAQEBAQEBAQEBAQEBAQEBAQEBAAAAAAAAAAAAAAAAAAABAQEBAQEBAQEBAQEBAQEBAQEAAAAAAAAAAAAAAAAAAAEBAQEBAQEBAQEBAQEBAQEBAQAAAAAAAAAAAAAAAAAAAQEBAQEBAQEBAQEBAAAAAAAAAAAAAAAAAAAAAAAAAAABAQEBAQEBAQEBAQEAAAAAAAAAAAAAAAAAAAAAAAAAAAEBAQEBAQEBAQEBAQAAAAAAAAAAAAAAAAAAAQEBAQEBAQEBAQEBAQEBAQEBAAAAAAAAAAAAAAAAAAABAQEBAQEBAQEBAQEBAQEBAQEAAAAAAAAAAAAAAAAAAAEBAQEBAQEBAQEBAQEBAQEBAQAAAAAAAAAAAAAAAAAAAQEBAQEBAQEBAQEBAQEBAQEBAAAAAAAAAAAAAAAAAAABAQEBAQEBAQEBAQEBAQEBAQEAAAAAAAAAAAAAAAAAAAEBAQEBAQEBAQEBAQ==" + }, + "palette" : { + "originalArgb8888" : [ -265674 ], + "convertedRgb565" : [ -122 ] } }, "diagnostics" : [ ] @@ -330,14 +330,14 @@ "last_modified" : 1774359772426, "fingerprint" : "eeb7cc665386299403b7be1c272375d5077f3647c587f8033aa8c9275f840562", "metadata" : { - "palette" : { - "originalArgb8888" : [ -265674 ], - "convertedRgb565" : [ -122 ] - }, "tile" : { "width" : 32, "height" : 32, "paletteIndices" : "AQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAAAAAAAAAAABAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEAAAAAAAAAAAEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQAAAAAAAAAAAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAAAAAAAAAAABAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEAAAAAAAAAAAEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQAAAAAAAAAAAQEBAQEBAQEBAQEBAAAAAAAAAAAAAAAAAAAAAAAAAAABAQEBAQEBAQEBAQEAAAAAAAAAAAAAAAAAAAAAAAAAAAEBAQEBAQEBAQEBAQAAAAAAAAAAAAAAAAAAAAAAAAAAAQEBAQEBAQEBAQEBAAAAAAAAAAAAAAAAAAAAAAAAAAABAQEBAQEBAQEBAQEAAAAAAAAAAAAAAAAAAAAAAAAAAAEBAQEBAQEBAQEBAQAAAAAAAAAAAAAAAAAAAAAAAAAAAQEBAQEBAQEBAQEBAAAAAAAAAAAAAAAAAAAAAAAAAAABAQEBAQEBAQEBAQEAAAAAAAAAAAAAAAAAAAAAAAAAAAEBAQEBAQEBAQEBAQAAAAAAAAAAAAAAAAAAAQEBAQEBAQEBAQEBAQEBAQEBAAAAAAAAAAAAAAAAAAABAQEBAQEBAQEBAQEBAQEBAQEAAAAAAAAAAAAAAAAAAAEBAQEBAQEBAQEBAQEBAQEBAQAAAAAAAAAAAAAAAAAAAQEBAQEBAQEBAQEBAAAAAAAAAAAAAAAAAAAAAAAAAAABAQEBAQEBAQEBAQEAAAAAAAAAAAAAAAAAAAAAAAAAAAEBAQEBAQEBAQEBAQAAAAAAAAAAAAAAAAAAAQEBAQEBAQEBAQEBAQEBAQEBAAAAAAAAAAAAAAAAAAABAQEBAQEBAQEBAQEBAQEBAQEAAAAAAAAAAAAAAAAAAAEBAQEBAQEBAQEBAQEBAQEBAQAAAAAAAAAAAAAAAAAAAQEBAQEBAQEBAQEBAQEBAQEBAAAAAAAAAAAAAAAAAAABAQEBAQEBAQEBAQEBAQEBAQEAAAAAAAAAAAAAAAAAAAEBAQEBAQEBAQEBAQ==" + }, + "palette" : { + "originalArgb8888" : [ -265674 ], + "convertedRgb565" : [ -122 ] } }, "diagnostics" : [ ] @@ -348,14 +348,14 @@ "last_modified" : 1774359772428, "fingerprint" : "eeb7cc665386299403b7be1c272375d5077f3647c587f8033aa8c9275f840562", "metadata" : { - "palette" : { - "originalArgb8888" : [ -265674 ], - "convertedRgb565" : [ -122 ] - }, "tile" : { "width" : 32, "height" : 32, "paletteIndices" : "AQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAAAAAAAAAAABAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEAAAAAAAAAAAEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQAAAAAAAAAAAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAAAAAAAAAAABAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEAAAAAAAAAAAEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQAAAAAAAAAAAQEBAQEBAQEBAQEBAAAAAAAAAAAAAAAAAAAAAAAAAAABAQEBAQEBAQEBAQEAAAAAAAAAAAAAAAAAAAAAAAAAAAEBAQEBAQEBAQEBAQAAAAAAAAAAAAAAAAAAAAAAAAAAAQEBAQEBAQEBAQEBAAAAAAAAAAAAAAAAAAAAAAAAAAABAQEBAQEBAQEBAQEAAAAAAAAAAAAAAAAAAAAAAAAAAAEBAQEBAQEBAQEBAQAAAAAAAAAAAAAAAAAAAAAAAAAAAQEBAQEBAQEBAQEBAAAAAAAAAAAAAAAAAAAAAAAAAAABAQEBAQEBAQEBAQEAAAAAAAAAAAAAAAAAAAAAAAAAAAEBAQEBAQEBAQEBAQAAAAAAAAAAAAAAAAAAAQEBAQEBAQEBAQEBAQEBAQEBAAAAAAAAAAAAAAAAAAABAQEBAQEBAQEBAQEBAQEBAQEAAAAAAAAAAAAAAAAAAAEBAQEBAQEBAQEBAQEBAQEBAQAAAAAAAAAAAAAAAAAAAQEBAQEBAQEBAQEBAAAAAAAAAAAAAAAAAAAAAAAAAAABAQEBAQEBAQEBAQEAAAAAAAAAAAAAAAAAAAAAAAAAAAEBAQEBAQEBAQEBAQAAAAAAAAAAAAAAAAAAAQEBAQEBAQEBAQEBAQEBAQEBAAAAAAAAAAAAAAAAAAABAQEBAQEBAQEBAQEBAQEBAQEAAAAAAAAAAAAAAAAAAAEBAQEBAQEBAQEBAQEBAQEBAQAAAAAAAAAAAAAAAAAAAQEBAQEBAQEBAQEBAQEBAQEBAAAAAAAAAAAAAAAAAAABAQEBAQEBAQEBAQEBAQEBAQEAAAAAAAAAAAAAAAAAAAEBAQEBAQEBAQEBAQ==" + }, + "palette" : { + "originalArgb8888" : [ -265674 ], + "convertedRgb565" : [ -122 ] } }, "diagnostics" : [ ] @@ -366,14 +366,14 @@ "last_modified" : 1774359772429, "fingerprint" : "eeb7cc665386299403b7be1c272375d5077f3647c587f8033aa8c9275f840562", "metadata" : { - "palette" : { - "originalArgb8888" : [ -265674 ], - "convertedRgb565" : [ -122 ] - }, "tile" : { "width" : 32, "height" : 32, "paletteIndices" : "AQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAAAAAAAAAAABAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEAAAAAAAAAAAEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQAAAAAAAAAAAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAAAAAAAAAAABAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEAAAAAAAAAAAEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQAAAAAAAAAAAQEBAQEBAQEBAQEBAAAAAAAAAAAAAAAAAAAAAAAAAAABAQEBAQEBAQEBAQEAAAAAAAAAAAAAAAAAAAAAAAAAAAEBAQEBAQEBAQEBAQAAAAAAAAAAAAAAAAAAAAAAAAAAAQEBAQEBAQEBAQEBAAAAAAAAAAAAAAAAAAAAAAAAAAABAQEBAQEBAQEBAQEAAAAAAAAAAAAAAAAAAAAAAAAAAAEBAQEBAQEBAQEBAQAAAAAAAAAAAAAAAAAAAAAAAAAAAQEBAQEBAQEBAQEBAAAAAAAAAAAAAAAAAAAAAAAAAAABAQEBAQEBAQEBAQEAAAAAAAAAAAAAAAAAAAAAAAAAAAEBAQEBAQEBAQEBAQAAAAAAAAAAAAAAAAAAAQEBAQEBAQEBAQEBAQEBAQEBAAAAAAAAAAAAAAAAAAABAQEBAQEBAQEBAQEBAQEBAQEAAAAAAAAAAAAAAAAAAAEBAQEBAQEBAQEBAQEBAQEBAQAAAAAAAAAAAAAAAAAAAQEBAQEBAQEBAQEBAAAAAAAAAAAAAAAAAAAAAAAAAAABAQEBAQEBAQEBAQEAAAAAAAAAAAAAAAAAAAAAAAAAAAEBAQEBAQEBAQEBAQAAAAAAAAAAAAAAAAAAAQEBAQEBAQEBAQEBAQEBAQEBAAAAAAAAAAAAAAAAAAABAQEBAQEBAQEBAQEBAQEBAQEAAAAAAAAAAAAAAAAAAAEBAQEBAQEBAQEBAQEBAQEBAQAAAAAAAAAAAAAAAAAAAQEBAQEBAQEBAQEBAQEBAQEBAAAAAAAAAAAAAAAAAAABAQEBAQEBAQEBAQEBAQEBAQEAAAAAAAAAAAAAAAAAAAEBAQEBAQEBAQEBAQ==" + }, + "palette" : { + "originalArgb8888" : [ -265674 ], + "convertedRgb565" : [ -122 ] } }, "diagnostics" : [ ] @@ -384,14 +384,14 @@ "last_modified" : 1774359772430, "fingerprint" : "eeb7cc665386299403b7be1c272375d5077f3647c587f8033aa8c9275f840562", "metadata" : { - "palette" : { - "originalArgb8888" : [ -265674 ], - "convertedRgb565" : [ -122 ] - }, "tile" : { "width" : 32, "height" : 32, "paletteIndices" : "AQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAAAAAAAAAAABAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEAAAAAAAAAAAEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQAAAAAAAAAAAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAAAAAAAAAAABAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEAAAAAAAAAAAEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQAAAAAAAAAAAQEBAQEBAQEBAQEBAAAAAAAAAAAAAAAAAAAAAAAAAAABAQEBAQEBAQEBAQEAAAAAAAAAAAAAAAAAAAAAAAAAAAEBAQEBAQEBAQEBAQAAAAAAAAAAAAAAAAAAAAAAAAAAAQEBAQEBAQEBAQEBAAAAAAAAAAAAAAAAAAAAAAAAAAABAQEBAQEBAQEBAQEAAAAAAAAAAAAAAAAAAAAAAAAAAAEBAQEBAQEBAQEBAQAAAAAAAAAAAAAAAAAAAAAAAAAAAQEBAQEBAQEBAQEBAAAAAAAAAAAAAAAAAAAAAAAAAAABAQEBAQEBAQEBAQEAAAAAAAAAAAAAAAAAAAAAAAAAAAEBAQEBAQEBAQEBAQAAAAAAAAAAAAAAAAAAAQEBAQEBAQEBAQEBAQEBAQEBAAAAAAAAAAAAAAAAAAABAQEBAQEBAQEBAQEBAQEBAQEAAAAAAAAAAAAAAAAAAAEBAQEBAQEBAQEBAQEBAQEBAQAAAAAAAAAAAAAAAAAAAQEBAQEBAQEBAQEBAAAAAAAAAAAAAAAAAAAAAAAAAAABAQEBAQEBAQEBAQEAAAAAAAAAAAAAAAAAAAAAAAAAAAEBAQEBAQEBAQEBAQAAAAAAAAAAAAAAAAAAAQEBAQEBAQEBAQEBAQEBAQEBAAAAAAAAAAAAAAAAAAABAQEBAQEBAQEBAQEBAQEBAQEAAAAAAAAAAAAAAAAAAAEBAQEBAQEBAQEBAQEBAQEBAQAAAAAAAAAAAAAAAAAAAQEBAQEBAQEBAQEBAQEBAQEBAAAAAAAAAAAAAAAAAAABAQEBAQEBAQEBAQEBAQEBAQEAAAAAAAAAAAAAAAAAAAEBAQEBAQEBAQEBAQ==" + }, + "palette" : { + "originalArgb8888" : [ -265674 ], + "convertedRgb565" : [ -122 ] } }, "diagnostics" : [ ] @@ -402,14 +402,14 @@ "last_modified" : 1774359772431, "fingerprint" : "eeb7cc665386299403b7be1c272375d5077f3647c587f8033aa8c9275f840562", "metadata" : { - "palette" : { - "originalArgb8888" : [ -265674 ], - "convertedRgb565" : [ -122 ] - }, "tile" : { "width" : 32, "height" : 32, "paletteIndices" : "AQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAAAAAAAAAAABAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEAAAAAAAAAAAEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQAAAAAAAAAAAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAAAAAAAAAAABAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEAAAAAAAAAAAEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQAAAAAAAAAAAQEBAQEBAQEBAQEBAAAAAAAAAAAAAAAAAAAAAAAAAAABAQEBAQEBAQEBAQEAAAAAAAAAAAAAAAAAAAAAAAAAAAEBAQEBAQEBAQEBAQAAAAAAAAAAAAAAAAAAAAAAAAAAAQEBAQEBAQEBAQEBAAAAAAAAAAAAAAAAAAAAAAAAAAABAQEBAQEBAQEBAQEAAAAAAAAAAAAAAAAAAAAAAAAAAAEBAQEBAQEBAQEBAQAAAAAAAAAAAAAAAAAAAAAAAAAAAQEBAQEBAQEBAQEBAAAAAAAAAAAAAAAAAAAAAAAAAAABAQEBAQEBAQEBAQEAAAAAAAAAAAAAAAAAAAAAAAAAAAEBAQEBAQEBAQEBAQAAAAAAAAAAAAAAAAAAAQEBAQEBAQEBAQEBAQEBAQEBAAAAAAAAAAAAAAAAAAABAQEBAQEBAQEBAQEBAQEBAQEAAAAAAAAAAAAAAAAAAAEBAQEBAQEBAQEBAQEBAQEBAQAAAAAAAAAAAAAAAAAAAQEBAQEBAQEBAQEBAAAAAAAAAAAAAAAAAAAAAAAAAAABAQEBAQEBAQEBAQEAAAAAAAAAAAAAAAAAAAAAAAAAAAEBAQEBAQEBAQEBAQAAAAAAAAAAAAAAAAAAAQEBAQEBAQEBAQEBAQEBAQEBAAAAAAAAAAAAAAAAAAABAQEBAQEBAQEBAQEBAQEBAQEAAAAAAAAAAAAAAAAAAAEBAQEBAQEBAQEBAQEBAQEBAQAAAAAAAAAAAAAAAAAAAQEBAQEBAQEBAQEBAQEBAQEBAAAAAAAAAAAAAAAAAAABAQEBAQEBAQEBAQEBAQEBAQEAAAAAAAAAAAAAAAAAAAEBAQEBAQEBAQEBAQ==" + }, + "palette" : { + "originalArgb8888" : [ -265674 ], + "convertedRgb565" : [ -122 ] } }, "diagnostics" : [ ] @@ -420,14 +420,14 @@ "last_modified" : 1774359772432, "fingerprint" : "eeb7cc665386299403b7be1c272375d5077f3647c587f8033aa8c9275f840562", "metadata" : { - "palette" : { - "originalArgb8888" : [ -265674 ], - "convertedRgb565" : [ -122 ] - }, "tile" : { "width" : 32, "height" : 32, "paletteIndices" : "AQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAAAAAAAAAAABAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEAAAAAAAAAAAEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQAAAAAAAAAAAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAAAAAAAAAAABAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEAAAAAAAAAAAEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQAAAAAAAAAAAQEBAQEBAQEBAQEBAAAAAAAAAAAAAAAAAAAAAAAAAAABAQEBAQEBAQEBAQEAAAAAAAAAAAAAAAAAAAAAAAAAAAEBAQEBAQEBAQEBAQAAAAAAAAAAAAAAAAAAAAAAAAAAAQEBAQEBAQEBAQEBAAAAAAAAAAAAAAAAAAAAAAAAAAABAQEBAQEBAQEBAQEAAAAAAAAAAAAAAAAAAAAAAAAAAAEBAQEBAQEBAQEBAQAAAAAAAAAAAAAAAAAAAAAAAAAAAQEBAQEBAQEBAQEBAAAAAAAAAAAAAAAAAAAAAAAAAAABAQEBAQEBAQEBAQEAAAAAAAAAAAAAAAAAAAAAAAAAAAEBAQEBAQEBAQEBAQAAAAAAAAAAAAAAAAAAAQEBAQEBAQEBAQEBAQEBAQEBAAAAAAAAAAAAAAAAAAABAQEBAQEBAQEBAQEBAQEBAQEAAAAAAAAAAAAAAAAAAAEBAQEBAQEBAQEBAQEBAQEBAQAAAAAAAAAAAAAAAAAAAQEBAQEBAQEBAQEBAAAAAAAAAAAAAAAAAAAAAAAAAAABAQEBAQEBAQEBAQEAAAAAAAAAAAAAAAAAAAAAAAAAAAEBAQEBAQEBAQEBAQAAAAAAAAAAAAAAAAAAAQEBAQEBAQEBAQEBAQEBAQEBAAAAAAAAAAAAAAAAAAABAQEBAQEBAQEBAQEBAQEBAQEAAAAAAAAAAAAAAAAAAAEBAQEBAQEBAQEBAQEBAQEBAQAAAAAAAAAAAAAAAAAAAQEBAQEBAQEBAQEBAQEBAQEBAAAAAAAAAAAAAAAAAAABAQEBAQEBAQEBAQEBAQEBAQEAAAAAAAAAAAAAAAAAAAEBAQEBAQEBAQEBAQ==" + }, + "palette" : { + "originalArgb8888" : [ -265674 ], + "convertedRgb565" : [ -122 ] } }, "diagnostics" : [ ] @@ -438,14 +438,14 @@ "last_modified" : 1774359772433, "fingerprint" : "eeb7cc665386299403b7be1c272375d5077f3647c587f8033aa8c9275f840562", "metadata" : { - "palette" : { - "originalArgb8888" : [ -265674 ], - "convertedRgb565" : [ -122 ] - }, "tile" : { "width" : 32, "height" : 32, "paletteIndices" : "AQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAAAAAAAAAAABAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEAAAAAAAAAAAEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQAAAAAAAAAAAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAAAAAAAAAAABAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEAAAAAAAAAAAEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQAAAAAAAAAAAQEBAQEBAQEBAQEBAAAAAAAAAAAAAAAAAAAAAAAAAAABAQEBAQEBAQEBAQEAAAAAAAAAAAAAAAAAAAAAAAAAAAEBAQEBAQEBAQEBAQAAAAAAAAAAAAAAAAAAAAAAAAAAAQEBAQEBAQEBAQEBAAAAAAAAAAAAAAAAAAAAAAAAAAABAQEBAQEBAQEBAQEAAAAAAAAAAAAAAAAAAAAAAAAAAAEBAQEBAQEBAQEBAQAAAAAAAAAAAAAAAAAAAAAAAAAAAQEBAQEBAQEBAQEBAAAAAAAAAAAAAAAAAAAAAAAAAAABAQEBAQEBAQEBAQEAAAAAAAAAAAAAAAAAAAAAAAAAAAEBAQEBAQEBAQEBAQAAAAAAAAAAAAAAAAAAAQEBAQEBAQEBAQEBAQEBAQEBAAAAAAAAAAAAAAAAAAABAQEBAQEBAQEBAQEBAQEBAQEAAAAAAAAAAAAAAAAAAAEBAQEBAQEBAQEBAQEBAQEBAQAAAAAAAAAAAAAAAAAAAQEBAQEBAQEBAQEBAAAAAAAAAAAAAAAAAAAAAAAAAAABAQEBAQEBAQEBAQEAAAAAAAAAAAAAAAAAAAAAAAAAAAEBAQEBAQEBAQEBAQAAAAAAAAAAAAAAAAAAAQEBAQEBAQEBAQEBAQEBAQEBAAAAAAAAAAAAAAAAAAABAQEBAQEBAQEBAQEBAQEBAQEAAAAAAAAAAAAAAAAAAAEBAQEBAQEBAQEBAQEBAQEBAQAAAAAAAAAAAAAAAAAAAQEBAQEBAQEBAQEBAQEBAQEBAAAAAAAAAAAAAAAAAAABAQEBAQEBAQEBAQEBAQEBAQEAAAAAAAAAAAAAAAAAAAEBAQEBAQEBAQEBAQ==" + }, + "palette" : { + "originalArgb8888" : [ -265674 ], + "convertedRgb565" : [ -122 ] } }, "diagnostics" : [ ] @@ -456,14 +456,14 @@ "last_modified" : 1774359772435, "fingerprint" : "eeb7cc665386299403b7be1c272375d5077f3647c587f8033aa8c9275f840562", "metadata" : { - "palette" : { - "originalArgb8888" : [ -265674 ], - "convertedRgb565" : [ -122 ] - }, "tile" : { "width" : 32, "height" : 32, "paletteIndices" : "AQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAAAAAAAAAAABAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEAAAAAAAAAAAEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQAAAAAAAAAAAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAAAAAAAAAAABAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEAAAAAAAAAAAEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQAAAAAAAAAAAQEBAQEBAQEBAQEBAAAAAAAAAAAAAAAAAAAAAAAAAAABAQEBAQEBAQEBAQEAAAAAAAAAAAAAAAAAAAAAAAAAAAEBAQEBAQEBAQEBAQAAAAAAAAAAAAAAAAAAAAAAAAAAAQEBAQEBAQEBAQEBAAAAAAAAAAAAAAAAAAAAAAAAAAABAQEBAQEBAQEBAQEAAAAAAAAAAAAAAAAAAAAAAAAAAAEBAQEBAQEBAQEBAQAAAAAAAAAAAAAAAAAAAAAAAAAAAQEBAQEBAQEBAQEBAAAAAAAAAAAAAAAAAAAAAAAAAAABAQEBAQEBAQEBAQEAAAAAAAAAAAAAAAAAAAAAAAAAAAEBAQEBAQEBAQEBAQAAAAAAAAAAAAAAAAAAAQEBAQEBAQEBAQEBAQEBAQEBAAAAAAAAAAAAAAAAAAABAQEBAQEBAQEBAQEBAQEBAQEAAAAAAAAAAAAAAAAAAAEBAQEBAQEBAQEBAQEBAQEBAQAAAAAAAAAAAAAAAAAAAQEBAQEBAQEBAQEBAAAAAAAAAAAAAAAAAAAAAAAAAAABAQEBAQEBAQEBAQEAAAAAAAAAAAAAAAAAAAAAAAAAAAEBAQEBAQEBAQEBAQAAAAAAAAAAAAAAAAAAAQEBAQEBAQEBAQEBAQEBAQEBAAAAAAAAAAAAAAAAAAABAQEBAQEBAQEBAQEBAQEBAQEAAAAAAAAAAAAAAAAAAAEBAQEBAQEBAQEBAQEBAQEBAQAAAAAAAAAAAAAAAAAAAQEBAQEBAQEBAQEBAQEBAQEBAAAAAAAAAAAAAAAAAAABAQEBAQEBAQEBAQEBAQEBAQEAAAAAAAAAAAAAAAAAAAEBAQEBAQEBAQEBAQ==" + }, + "palette" : { + "originalArgb8888" : [ -265674 ], + "convertedRgb565" : [ -122 ] } }, "diagnostics" : [ ] @@ -474,14 +474,14 @@ "last_modified" : 1774359772436, "fingerprint" : "eeb7cc665386299403b7be1c272375d5077f3647c587f8033aa8c9275f840562", "metadata" : { - "palette" : { - "originalArgb8888" : [ -265674 ], - "convertedRgb565" : [ -122 ] - }, "tile" : { "width" : 32, "height" : 32, "paletteIndices" : "AQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAAAAAAAAAAABAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEAAAAAAAAAAAEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQAAAAAAAAAAAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAAAAAAAAAAABAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEAAAAAAAAAAAEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQAAAAAAAAAAAQEBAQEBAQEBAQEBAAAAAAAAAAAAAAAAAAAAAAAAAAABAQEBAQEBAQEBAQEAAAAAAAAAAAAAAAAAAAAAAAAAAAEBAQEBAQEBAQEBAQAAAAAAAAAAAAAAAAAAAAAAAAAAAQEBAQEBAQEBAQEBAAAAAAAAAAAAAAAAAAAAAAAAAAABAQEBAQEBAQEBAQEAAAAAAAAAAAAAAAAAAAAAAAAAAAEBAQEBAQEBAQEBAQAAAAAAAAAAAAAAAAAAAAAAAAAAAQEBAQEBAQEBAQEBAAAAAAAAAAAAAAAAAAAAAAAAAAABAQEBAQEBAQEBAQEAAAAAAAAAAAAAAAAAAAAAAAAAAAEBAQEBAQEBAQEBAQAAAAAAAAAAAAAAAAAAAQEBAQEBAQEBAQEBAQEBAQEBAAAAAAAAAAAAAAAAAAABAQEBAQEBAQEBAQEBAQEBAQEAAAAAAAAAAAAAAAAAAAEBAQEBAQEBAQEBAQEBAQEBAQAAAAAAAAAAAAAAAAAAAQEBAQEBAQEBAQEBAAAAAAAAAAAAAAAAAAAAAAAAAAABAQEBAQEBAQEBAQEAAAAAAAAAAAAAAAAAAAAAAAAAAAEBAQEBAQEBAQEBAQAAAAAAAAAAAAAAAAAAAQEBAQEBAQEBAQEBAQEBAQEBAAAAAAAAAAAAAAAAAAABAQEBAQEBAQEBAQEBAQEBAQEAAAAAAAAAAAAAAAAAAAEBAQEBAQEBAQEBAQEBAQEBAQAAAAAAAAAAAAAAAAAAAQEBAQEBAQEBAQEBAQEBAQEBAAAAAAAAAAAAAAAAAAABAQEBAQEBAQEBAQEBAQEBAQEAAAAAAAAAAAAAAAAAAAEBAQEBAQEBAQEBAQ==" + }, + "palette" : { + "originalArgb8888" : [ -265674 ], + "convertedRgb565" : [ -122 ] } }, "diagnostics" : [ ] @@ -492,14 +492,14 @@ "last_modified" : 1774359772437, "fingerprint" : "eeb7cc665386299403b7be1c272375d5077f3647c587f8033aa8c9275f840562", "metadata" : { - "palette" : { - "originalArgb8888" : [ -265674 ], - "convertedRgb565" : [ -122 ] - }, "tile" : { "width" : 32, "height" : 32, "paletteIndices" : "AQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAAAAAAAAAAABAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEAAAAAAAAAAAEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQAAAAAAAAAAAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAAAAAAAAAAABAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEAAAAAAAAAAAEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQAAAAAAAAAAAQEBAQEBAQEBAQEBAAAAAAAAAAAAAAAAAAAAAAAAAAABAQEBAQEBAQEBAQEAAAAAAAAAAAAAAAAAAAAAAAAAAAEBAQEBAQEBAQEBAQAAAAAAAAAAAAAAAAAAAAAAAAAAAQEBAQEBAQEBAQEBAAAAAAAAAAAAAAAAAAAAAAAAAAABAQEBAQEBAQEBAQEAAAAAAAAAAAAAAAAAAAAAAAAAAAEBAQEBAQEBAQEBAQAAAAAAAAAAAAAAAAAAAAAAAAAAAQEBAQEBAQEBAQEBAAAAAAAAAAAAAAAAAAAAAAAAAAABAQEBAQEBAQEBAQEAAAAAAAAAAAAAAAAAAAAAAAAAAAEBAQEBAQEBAQEBAQAAAAAAAAAAAAAAAAAAAQEBAQEBAQEBAQEBAQEBAQEBAAAAAAAAAAAAAAAAAAABAQEBAQEBAQEBAQEBAQEBAQEAAAAAAAAAAAAAAAAAAAEBAQEBAQEBAQEBAQEBAQEBAQAAAAAAAAAAAAAAAAAAAQEBAQEBAQEBAQEBAAAAAAAAAAAAAAAAAAAAAAAAAAABAQEBAQEBAQEBAQEAAAAAAAAAAAAAAAAAAAAAAAAAAAEBAQEBAQEBAQEBAQAAAAAAAAAAAAAAAAAAAQEBAQEBAQEBAQEBAQEBAQEBAAAAAAAAAAAAAAAAAAABAQEBAQEBAQEBAQEBAQEBAQEAAAAAAAAAAAAAAAAAAAEBAQEBAQEBAQEBAQEBAQEBAQAAAAAAAAAAAAAAAAAAAQEBAQEBAQEBAQEBAQEBAQEBAAAAAAAAAAAAAAAAAAABAQEBAQEBAQEBAQEBAQEBAQEAAAAAAAAAAAAAAAAAAAEBAQEBAQEBAQEBAQ==" + }, + "palette" : { + "originalArgb8888" : [ -265674 ], + "convertedRgb565" : [ -122 ] } }, "diagnostics" : [ ] @@ -510,14 +510,14 @@ "last_modified" : 1774359772438, "fingerprint" : "eeb7cc665386299403b7be1c272375d5077f3647c587f8033aa8c9275f840562", "metadata" : { - "palette" : { - "originalArgb8888" : [ -265674 ], - "convertedRgb565" : [ -122 ] - }, "tile" : { "width" : 32, "height" : 32, "paletteIndices" : "AQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAAAAAAAAAAABAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEAAAAAAAAAAAEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQAAAAAAAAAAAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAAAAAAAAAAABAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEAAAAAAAAAAAEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQAAAAAAAAAAAQEBAQEBAQEBAQEBAAAAAAAAAAAAAAAAAAAAAAAAAAABAQEBAQEBAQEBAQEAAAAAAAAAAAAAAAAAAAAAAAAAAAEBAQEBAQEBAQEBAQAAAAAAAAAAAAAAAAAAAAAAAAAAAQEBAQEBAQEBAQEBAAAAAAAAAAAAAAAAAAAAAAAAAAABAQEBAQEBAQEBAQEAAAAAAAAAAAAAAAAAAAAAAAAAAAEBAQEBAQEBAQEBAQAAAAAAAAAAAAAAAAAAAAAAAAAAAQEBAQEBAQEBAQEBAAAAAAAAAAAAAAAAAAAAAAAAAAABAQEBAQEBAQEBAQEAAAAAAAAAAAAAAAAAAAAAAAAAAAEBAQEBAQEBAQEBAQAAAAAAAAAAAAAAAAAAAQEBAQEBAQEBAQEBAQEBAQEBAAAAAAAAAAAAAAAAAAABAQEBAQEBAQEBAQEBAQEBAQEAAAAAAAAAAAAAAAAAAAEBAQEBAQEBAQEBAQEBAQEBAQAAAAAAAAAAAAAAAAAAAQEBAQEBAQEBAQEBAAAAAAAAAAAAAAAAAAAAAAAAAAABAQEBAQEBAQEBAQEAAAAAAAAAAAAAAAAAAAAAAAAAAAEBAQEBAQEBAQEBAQAAAAAAAAAAAAAAAAAAAQEBAQEBAQEBAQEBAQEBAQEBAAAAAAAAAAAAAAAAAAABAQEBAQEBAQEBAQEBAQEBAQEAAAAAAAAAAAAAAAAAAAEBAQEBAQEBAQEBAQEBAQEBAQAAAAAAAAAAAAAAAAAAAQEBAQEBAQEBAQEBAQEBAQEBAAAAAAAAAAAAAAAAAAABAQEBAQEBAQEBAQEBAQEBAQEAAAAAAAAAAAAAAAAAAAEBAQEBAQEBAQEBAQ==" + }, + "palette" : { + "originalArgb8888" : [ -265674 ], + "convertedRgb565" : [ -122 ] } }, "diagnostics" : [ ] @@ -528,14 +528,14 @@ "last_modified" : 1774359772439, "fingerprint" : "eeb7cc665386299403b7be1c272375d5077f3647c587f8033aa8c9275f840562", "metadata" : { - "palette" : { - "originalArgb8888" : [ -265674 ], - "convertedRgb565" : [ -122 ] - }, "tile" : { "width" : 32, "height" : 32, "paletteIndices" : "AQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAAAAAAAAAAABAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEAAAAAAAAAAAEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQAAAAAAAAAAAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAAAAAAAAAAABAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEAAAAAAAAAAAEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQAAAAAAAAAAAQEBAQEBAQEBAQEBAAAAAAAAAAAAAAAAAAAAAAAAAAABAQEBAQEBAQEBAQEAAAAAAAAAAAAAAAAAAAAAAAAAAAEBAQEBAQEBAQEBAQAAAAAAAAAAAAAAAAAAAAAAAAAAAQEBAQEBAQEBAQEBAAAAAAAAAAAAAAAAAAAAAAAAAAABAQEBAQEBAQEBAQEAAAAAAAAAAAAAAAAAAAAAAAAAAAEBAQEBAQEBAQEBAQAAAAAAAAAAAAAAAAAAAAAAAAAAAQEBAQEBAQEBAQEBAAAAAAAAAAAAAAAAAAAAAAAAAAABAQEBAQEBAQEBAQEAAAAAAAAAAAAAAAAAAAAAAAAAAAEBAQEBAQEBAQEBAQAAAAAAAAAAAAAAAAAAAQEBAQEBAQEBAQEBAQEBAQEBAAAAAAAAAAAAAAAAAAABAQEBAQEBAQEBAQEBAQEBAQEAAAAAAAAAAAAAAAAAAAEBAQEBAQEBAQEBAQEBAQEBAQAAAAAAAAAAAAAAAAAAAQEBAQEBAQEBAQEBAAAAAAAAAAAAAAAAAAAAAAAAAAABAQEBAQEBAQEBAQEAAAAAAAAAAAAAAAAAAAAAAAAAAAEBAQEBAQEBAQEBAQAAAAAAAAAAAAAAAAAAAQEBAQEBAQEBAQEBAQEBAQEBAAAAAAAAAAAAAAAAAAABAQEBAQEBAQEBAQEBAQEBAQEAAAAAAAAAAAAAAAAAAAEBAQEBAQEBAQEBAQEBAQEBAQAAAAAAAAAAAAAAAAAAAQEBAQEBAQEBAQEBAQEBAQEBAAAAAAAAAAAAAAAAAAABAQEBAQEBAQEBAQEBAQEBAQEAAAAAAAAAAAAAAAAAAAEBAQEBAQEBAQEBAQ==" + }, + "palette" : { + "originalArgb8888" : [ -265674 ], + "convertedRgb565" : [ -122 ] } }, "diagnostics" : [ ] @@ -546,14 +546,14 @@ "last_modified" : 1774359772441, "fingerprint" : "eeb7cc665386299403b7be1c272375d5077f3647c587f8033aa8c9275f840562", "metadata" : { - "palette" : { - "originalArgb8888" : [ -265674 ], - "convertedRgb565" : [ -122 ] - }, "tile" : { "width" : 32, "height" : 32, "paletteIndices" : "AQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAAAAAAAAAAABAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEAAAAAAAAAAAEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQAAAAAAAAAAAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAAAAAAAAAAABAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEAAAAAAAAAAAEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQAAAAAAAAAAAQEBAQEBAQEBAQEBAAAAAAAAAAAAAAAAAAAAAAAAAAABAQEBAQEBAQEBAQEAAAAAAAAAAAAAAAAAAAAAAAAAAAEBAQEBAQEBAQEBAQAAAAAAAAAAAAAAAAAAAAAAAAAAAQEBAQEBAQEBAQEBAAAAAAAAAAAAAAAAAAAAAAAAAAABAQEBAQEBAQEBAQEAAAAAAAAAAAAAAAAAAAAAAAAAAAEBAQEBAQEBAQEBAQAAAAAAAAAAAAAAAAAAAAAAAAAAAQEBAQEBAQEBAQEBAAAAAAAAAAAAAAAAAAAAAAAAAAABAQEBAQEBAQEBAQEAAAAAAAAAAAAAAAAAAAAAAAAAAAEBAQEBAQEBAQEBAQAAAAAAAAAAAAAAAAAAAQEBAQEBAQEBAQEBAQEBAQEBAAAAAAAAAAAAAAAAAAABAQEBAQEBAQEBAQEBAQEBAQEAAAAAAAAAAAAAAAAAAAEBAQEBAQEBAQEBAQEBAQEBAQAAAAAAAAAAAAAAAAAAAQEBAQEBAQEBAQEBAAAAAAAAAAAAAAAAAAAAAAAAAAABAQEBAQEBAQEBAQEAAAAAAAAAAAAAAAAAAAAAAAAAAAEBAQEBAQEBAQEBAQAAAAAAAAAAAAAAAAAAAQEBAQEBAQEBAQEBAQEBAQEBAAAAAAAAAAAAAAAAAAABAQEBAQEBAQEBAQEBAQEBAQEAAAAAAAAAAAAAAAAAAAEBAQEBAQEBAQEBAQEBAQEBAQAAAAAAAAAAAAAAAAAAAQEBAQEBAQEBAQEBAQEBAQEBAAAAAAAAAAAAAAAAAAABAQEBAQEBAQEBAQEBAQEBAQEAAAAAAAAAAAAAAAAAAAEBAQEBAQEBAQEBAQ==" + }, + "palette" : { + "originalArgb8888" : [ -265674 ], + "convertedRgb565" : [ -122 ] } }, "diagnostics" : [ ] @@ -564,14 +564,14 @@ "last_modified" : 1774359772442, "fingerprint" : "eeb7cc665386299403b7be1c272375d5077f3647c587f8033aa8c9275f840562", "metadata" : { - "palette" : { - "originalArgb8888" : [ -265674 ], - "convertedRgb565" : [ -122 ] - }, "tile" : { "width" : 32, "height" : 32, "paletteIndices" : "AQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAAAAAAAAAAABAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEAAAAAAAAAAAEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQAAAAAAAAAAAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAAAAAAAAAAABAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEAAAAAAAAAAAEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQAAAAAAAAAAAQEBAQEBAQEBAQEBAAAAAAAAAAAAAAAAAAAAAAAAAAABAQEBAQEBAQEBAQEAAAAAAAAAAAAAAAAAAAAAAAAAAAEBAQEBAQEBAQEBAQAAAAAAAAAAAAAAAAAAAAAAAAAAAQEBAQEBAQEBAQEBAAAAAAAAAAAAAAAAAAAAAAAAAAABAQEBAQEBAQEBAQEAAAAAAAAAAAAAAAAAAAAAAAAAAAEBAQEBAQEBAQEBAQAAAAAAAAAAAAAAAAAAAAAAAAAAAQEBAQEBAQEBAQEBAAAAAAAAAAAAAAAAAAAAAAAAAAABAQEBAQEBAQEBAQEAAAAAAAAAAAAAAAAAAAAAAAAAAAEBAQEBAQEBAQEBAQAAAAAAAAAAAAAAAAAAAQEBAQEBAQEBAQEBAQEBAQEBAAAAAAAAAAAAAAAAAAABAQEBAQEBAQEBAQEBAQEBAQEAAAAAAAAAAAAAAAAAAAEBAQEBAQEBAQEBAQEBAQEBAQAAAAAAAAAAAAAAAAAAAQEBAQEBAQEBAQEBAAAAAAAAAAAAAAAAAAAAAAAAAAABAQEBAQEBAQEBAQEAAAAAAAAAAAAAAAAAAAAAAAAAAAEBAQEBAQEBAQEBAQAAAAAAAAAAAAAAAAAAAQEBAQEBAQEBAQEBAQEBAQEBAAAAAAAAAAAAAAAAAAABAQEBAQEBAQEBAQEBAQEBAQEAAAAAAAAAAAAAAAAAAAEBAQEBAQEBAQEBAQEBAQEBAQAAAAAAAAAAAAAAAAAAAQEBAQEBAQEBAQEBAQEBAQEBAAAAAAAAAAAAAAAAAAABAQEBAQEBAQEBAQEBAQEBAQEAAAAAAAAAAAAAAAAAAAEBAQEBAQEBAQEBAQ==" + }, + "palette" : { + "originalArgb8888" : [ -265674 ], + "convertedRgb565" : [ -122 ] } }, "diagnostics" : [ ] @@ -582,14 +582,14 @@ "last_modified" : 1774359772443, "fingerprint" : "eeb7cc665386299403b7be1c272375d5077f3647c587f8033aa8c9275f840562", "metadata" : { - "palette" : { - "originalArgb8888" : [ -265674 ], - "convertedRgb565" : [ -122 ] - }, "tile" : { "width" : 32, "height" : 32, "paletteIndices" : "AQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAAAAAAAAAAABAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEAAAAAAAAAAAEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQAAAAAAAAAAAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAAAAAAAAAAABAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEAAAAAAAAAAAEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQAAAAAAAAAAAQEBAQEBAQEBAQEBAAAAAAAAAAAAAAAAAAAAAAAAAAABAQEBAQEBAQEBAQEAAAAAAAAAAAAAAAAAAAAAAAAAAAEBAQEBAQEBAQEBAQAAAAAAAAAAAAAAAAAAAAAAAAAAAQEBAQEBAQEBAQEBAAAAAAAAAAAAAAAAAAAAAAAAAAABAQEBAQEBAQEBAQEAAAAAAAAAAAAAAAAAAAAAAAAAAAEBAQEBAQEBAQEBAQAAAAAAAAAAAAAAAAAAAAAAAAAAAQEBAQEBAQEBAQEBAAAAAAAAAAAAAAAAAAAAAAAAAAABAQEBAQEBAQEBAQEAAAAAAAAAAAAAAAAAAAAAAAAAAAEBAQEBAQEBAQEBAQAAAAAAAAAAAAAAAAAAAQEBAQEBAQEBAQEBAQEBAQEBAAAAAAAAAAAAAAAAAAABAQEBAQEBAQEBAQEBAQEBAQEAAAAAAAAAAAAAAAAAAAEBAQEBAQEBAQEBAQEBAQEBAQAAAAAAAAAAAAAAAAAAAQEBAQEBAQEBAQEBAAAAAAAAAAAAAAAAAAAAAAAAAAABAQEBAQEBAQEBAQEAAAAAAAAAAAAAAAAAAAAAAAAAAAEBAQEBAQEBAQEBAQAAAAAAAAAAAAAAAAAAAQEBAQEBAQEBAQEBAQEBAQEBAAAAAAAAAAAAAAAAAAABAQEBAQEBAQEBAQEBAQEBAQEAAAAAAAAAAAAAAAAAAAEBAQEBAQEBAQEBAQEBAQEBAQAAAAAAAAAAAAAAAAAAAQEBAQEBAQEBAQEBAQEBAQEBAAAAAAAAAAAAAAAAAAABAQEBAQEBAQEBAQEBAQEBAQEAAAAAAAAAAAAAAAAAAAEBAQEBAQEBAQEBAQ==" + }, + "palette" : { + "originalArgb8888" : [ -265674 ], + "convertedRgb565" : [ -122 ] } }, "diagnostics" : [ ] @@ -600,14 +600,14 @@ "last_modified" : 1774359772444, "fingerprint" : "eeb7cc665386299403b7be1c272375d5077f3647c587f8033aa8c9275f840562", "metadata" : { - "palette" : { - "originalArgb8888" : [ -265674 ], - "convertedRgb565" : [ -122 ] - }, "tile" : { "width" : 32, "height" : 32, "paletteIndices" : "AQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAAAAAAAAAAABAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEAAAAAAAAAAAEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQAAAAAAAAAAAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAAAAAAAAAAABAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEAAAAAAAAAAAEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQAAAAAAAAAAAQEBAQEBAQEBAQEBAAAAAAAAAAAAAAAAAAAAAAAAAAABAQEBAQEBAQEBAQEAAAAAAAAAAAAAAAAAAAAAAAAAAAEBAQEBAQEBAQEBAQAAAAAAAAAAAAAAAAAAAAAAAAAAAQEBAQEBAQEBAQEBAAAAAAAAAAAAAAAAAAAAAAAAAAABAQEBAQEBAQEBAQEAAAAAAAAAAAAAAAAAAAAAAAAAAAEBAQEBAQEBAQEBAQAAAAAAAAAAAAAAAAAAAAAAAAAAAQEBAQEBAQEBAQEBAAAAAAAAAAAAAAAAAAAAAAAAAAABAQEBAQEBAQEBAQEAAAAAAAAAAAAAAAAAAAAAAAAAAAEBAQEBAQEBAQEBAQAAAAAAAAAAAAAAAAAAAQEBAQEBAQEBAQEBAQEBAQEBAAAAAAAAAAAAAAAAAAABAQEBAQEBAQEBAQEBAQEBAQEAAAAAAAAAAAAAAAAAAAEBAQEBAQEBAQEBAQEBAQEBAQAAAAAAAAAAAAAAAAAAAQEBAQEBAQEBAQEBAAAAAAAAAAAAAAAAAAAAAAAAAAABAQEBAQEBAQEBAQEAAAAAAAAAAAAAAAAAAAAAAAAAAAEBAQEBAQEBAQEBAQAAAAAAAAAAAAAAAAAAAQEBAQEBAQEBAQEBAQEBAQEBAAAAAAAAAAAAAAAAAAABAQEBAQEBAQEBAQEBAQEBAQEAAAAAAAAAAAAAAAAAAAEBAQEBAQEBAQEBAQEBAQEBAQAAAAAAAAAAAAAAAAAAAQEBAQEBAQEBAQEBAQEBAQEBAAAAAAAAAAAAAAAAAAABAQEBAQEBAQEBAQEBAQEBAQEAAAAAAAAAAAAAAAAAAAEBAQEBAQEBAQEBAQ==" + }, + "palette" : { + "originalArgb8888" : [ -265674 ], + "convertedRgb565" : [ -122 ] } }, "diagnostics" : [ ] @@ -618,14 +618,14 @@ "last_modified" : 1774359772445, "fingerprint" : "eeb7cc665386299403b7be1c272375d5077f3647c587f8033aa8c9275f840562", "metadata" : { - "palette" : { - "originalArgb8888" : [ -265674 ], - "convertedRgb565" : [ -122 ] - }, "tile" : { "width" : 32, "height" : 32, "paletteIndices" : "AQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAAAAAAAAAAABAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEAAAAAAAAAAAEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQAAAAAAAAAAAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAAAAAAAAAAABAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEAAAAAAAAAAAEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQAAAAAAAAAAAQEBAQEBAQEBAQEBAAAAAAAAAAAAAAAAAAAAAAAAAAABAQEBAQEBAQEBAQEAAAAAAAAAAAAAAAAAAAAAAAAAAAEBAQEBAQEBAQEBAQAAAAAAAAAAAAAAAAAAAAAAAAAAAQEBAQEBAQEBAQEBAAAAAAAAAAAAAAAAAAAAAAAAAAABAQEBAQEBAQEBAQEAAAAAAAAAAAAAAAAAAAAAAAAAAAEBAQEBAQEBAQEBAQAAAAAAAAAAAAAAAAAAAAAAAAAAAQEBAQEBAQEBAQEBAAAAAAAAAAAAAAAAAAAAAAAAAAABAQEBAQEBAQEBAQEAAAAAAAAAAAAAAAAAAAAAAAAAAAEBAQEBAQEBAQEBAQAAAAAAAAAAAAAAAAAAAQEBAQEBAQEBAQEBAQEBAQEBAAAAAAAAAAAAAAAAAAABAQEBAQEBAQEBAQEBAQEBAQEAAAAAAAAAAAAAAAAAAAEBAQEBAQEBAQEBAQEBAQEBAQAAAAAAAAAAAAAAAAAAAQEBAQEBAQEBAQEBAAAAAAAAAAAAAAAAAAAAAAAAAAABAQEBAQEBAQEBAQEAAAAAAAAAAAAAAAAAAAAAAAAAAAEBAQEBAQEBAQEBAQAAAAAAAAAAAAAAAAAAAQEBAQEBAQEBAQEBAQEBAQEBAAAAAAAAAAAAAAAAAAABAQEBAQEBAQEBAQEBAQEBAQEAAAAAAAAAAAAAAAAAAAEBAQEBAQEBAQEBAQEBAQEBAQAAAAAAAAAAAAAAAAAAAQEBAQEBAQEBAQEBAQEBAQEBAAAAAAAAAAAAAAAAAAABAQEBAQEBAQEBAQEBAQEBAQEAAAAAAAAAAAAAAAAAAAEBAQEBAQEBAQEBAQ==" + }, + "palette" : { + "originalArgb8888" : [ -265674 ], + "convertedRgb565" : [ -122 ] } }, "diagnostics" : [ ] @@ -636,14 +636,14 @@ "last_modified" : 1774359772448, "fingerprint" : "eeb7cc665386299403b7be1c272375d5077f3647c587f8033aa8c9275f840562", "metadata" : { - "palette" : { - "originalArgb8888" : [ -265674 ], - "convertedRgb565" : [ -122 ] - }, "tile" : { "width" : 32, "height" : 32, "paletteIndices" : "AQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAAAAAAAAAAABAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEAAAAAAAAAAAEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQAAAAAAAAAAAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAAAAAAAAAAABAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEAAAAAAAAAAAEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQAAAAAAAAAAAQEBAQEBAQEBAQEBAAAAAAAAAAAAAAAAAAAAAAAAAAABAQEBAQEBAQEBAQEAAAAAAAAAAAAAAAAAAAAAAAAAAAEBAQEBAQEBAQEBAQAAAAAAAAAAAAAAAAAAAAAAAAAAAQEBAQEBAQEBAQEBAAAAAAAAAAAAAAAAAAAAAAAAAAABAQEBAQEBAQEBAQEAAAAAAAAAAAAAAAAAAAAAAAAAAAEBAQEBAQEBAQEBAQAAAAAAAAAAAAAAAAAAAAAAAAAAAQEBAQEBAQEBAQEBAAAAAAAAAAAAAAAAAAAAAAAAAAABAQEBAQEBAQEBAQEAAAAAAAAAAAAAAAAAAAAAAAAAAAEBAQEBAQEBAQEBAQAAAAAAAAAAAAAAAAAAAQEBAQEBAQEBAQEBAQEBAQEBAAAAAAAAAAAAAAAAAAABAQEBAQEBAQEBAQEBAQEBAQEAAAAAAAAAAAAAAAAAAAEBAQEBAQEBAQEBAQEBAQEBAQAAAAAAAAAAAAAAAAAAAQEBAQEBAQEBAQEBAAAAAAAAAAAAAAAAAAAAAAAAAAABAQEBAQEBAQEBAQEAAAAAAAAAAAAAAAAAAAAAAAAAAAEBAQEBAQEBAQEBAQAAAAAAAAAAAAAAAAAAAQEBAQEBAQEBAQEBAQEBAQEBAAAAAAAAAAAAAAAAAAABAQEBAQEBAQEBAQEBAQEBAQEAAAAAAAAAAAAAAAAAAAEBAQEBAQEBAQEBAQEBAQEBAQAAAAAAAAAAAAAAAAAAAQEBAQEBAQEBAQEBAQEBAQEBAAAAAAAAAAAAAAAAAAABAQEBAQEBAQEBAQEBAQEBAQEAAAAAAAAAAAAAAAAAAAEBAQEBAQEBAQEBAQ==" + }, + "palette" : { + "originalArgb8888" : [ -265674 ], + "convertedRgb565" : [ -122 ] } }, "diagnostics" : [ ] @@ -654,14 +654,14 @@ "last_modified" : 1774359772449, "fingerprint" : "eeb7cc665386299403b7be1c272375d5077f3647c587f8033aa8c9275f840562", "metadata" : { - "palette" : { - "originalArgb8888" : [ -265674 ], - "convertedRgb565" : [ -122 ] - }, "tile" : { "width" : 32, "height" : 32, "paletteIndices" : "AQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAAAAAAAAAAABAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEAAAAAAAAAAAEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQAAAAAAAAAAAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAAAAAAAAAAABAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEAAAAAAAAAAAEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQAAAAAAAAAAAQEBAQEBAQEBAQEBAAAAAAAAAAAAAAAAAAAAAAAAAAABAQEBAQEBAQEBAQEAAAAAAAAAAAAAAAAAAAAAAAAAAAEBAQEBAQEBAQEBAQAAAAAAAAAAAAAAAAAAAAAAAAAAAQEBAQEBAQEBAQEBAAAAAAAAAAAAAAAAAAAAAAAAAAABAQEBAQEBAQEBAQEAAAAAAAAAAAAAAAAAAAAAAAAAAAEBAQEBAQEBAQEBAQAAAAAAAAAAAAAAAAAAAAAAAAAAAQEBAQEBAQEBAQEBAAAAAAAAAAAAAAAAAAAAAAAAAAABAQEBAQEBAQEBAQEAAAAAAAAAAAAAAAAAAAAAAAAAAAEBAQEBAQEBAQEBAQAAAAAAAAAAAAAAAAAAAQEBAQEBAQEBAQEBAQEBAQEBAAAAAAAAAAAAAAAAAAABAQEBAQEBAQEBAQEBAQEBAQEAAAAAAAAAAAAAAAAAAAEBAQEBAQEBAQEBAQEBAQEBAQAAAAAAAAAAAAAAAAAAAQEBAQEBAQEBAQEBAAAAAAAAAAAAAAAAAAAAAAAAAAABAQEBAQEBAQEBAQEAAAAAAAAAAAAAAAAAAAAAAAAAAAEBAQEBAQEBAQEBAQAAAAAAAAAAAAAAAAAAAQEBAQEBAQEBAQEBAQEBAQEBAAAAAAAAAAAAAAAAAAABAQEBAQEBAQEBAQEBAQEBAQEAAAAAAAAAAAAAAAAAAAEBAQEBAQEBAQEBAQEBAQEBAQAAAAAAAAAAAAAAAAAAAQEBAQEBAQEBAQEBAQEBAQEBAAAAAAAAAAAAAAAAAAABAQEBAQEBAQEBAQEBAQEBAQEAAAAAAAAAAAAAAAAAAAEBAQEBAQEBAQEBAQ==" + }, + "palette" : { + "originalArgb8888" : [ -265674 ], + "convertedRgb565" : [ -122 ] } }, "diagnostics" : [ ] @@ -672,14 +672,14 @@ "last_modified" : 1774359772450, "fingerprint" : "eeb7cc665386299403b7be1c272375d5077f3647c587f8033aa8c9275f840562", "metadata" : { - "palette" : { - "originalArgb8888" : [ -265674 ], - "convertedRgb565" : [ -122 ] - }, "tile" : { "width" : 32, "height" : 32, "paletteIndices" : "AQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAAAAAAAAAAABAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEAAAAAAAAAAAEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQAAAAAAAAAAAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAAAAAAAAAAABAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEAAAAAAAAAAAEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQAAAAAAAAAAAQEBAQEBAQEBAQEBAAAAAAAAAAAAAAAAAAAAAAAAAAABAQEBAQEBAQEBAQEAAAAAAAAAAAAAAAAAAAAAAAAAAAEBAQEBAQEBAQEBAQAAAAAAAAAAAAAAAAAAAAAAAAAAAQEBAQEBAQEBAQEBAAAAAAAAAAAAAAAAAAAAAAAAAAABAQEBAQEBAQEBAQEAAAAAAAAAAAAAAAAAAAAAAAAAAAEBAQEBAQEBAQEBAQAAAAAAAAAAAAAAAAAAAAAAAAAAAQEBAQEBAQEBAQEBAAAAAAAAAAAAAAAAAAAAAAAAAAABAQEBAQEBAQEBAQEAAAAAAAAAAAAAAAAAAAAAAAAAAAEBAQEBAQEBAQEBAQAAAAAAAAAAAAAAAAAAAQEBAQEBAQEBAQEBAQEBAQEBAAAAAAAAAAAAAAAAAAABAQEBAQEBAQEBAQEBAQEBAQEAAAAAAAAAAAAAAAAAAAEBAQEBAQEBAQEBAQEBAQEBAQAAAAAAAAAAAAAAAAAAAQEBAQEBAQEBAQEBAAAAAAAAAAAAAAAAAAAAAAAAAAABAQEBAQEBAQEBAQEAAAAAAAAAAAAAAAAAAAAAAAAAAAEBAQEBAQEBAQEBAQAAAAAAAAAAAAAAAAAAAQEBAQEBAQEBAQEBAQEBAQEBAAAAAAAAAAAAAAAAAAABAQEBAQEBAQEBAQEBAQEBAQEAAAAAAAAAAAAAAAAAAAEBAQEBAQEBAQEBAQEBAQEBAQAAAAAAAAAAAAAAAAAAAQEBAQEBAQEBAQEBAQEBAQEBAAAAAAAAAAAAAAAAAAABAQEBAQEBAQEBAQEBAQEBAQEAAAAAAAAAAAAAAAAAAAEBAQEBAQEBAQEBAQ==" + }, + "palette" : { + "originalArgb8888" : [ -265674 ], + "convertedRgb565" : [ -122 ] } }, "diagnostics" : [ ] @@ -690,14 +690,14 @@ "last_modified" : 1774359772452, "fingerprint" : "eeb7cc665386299403b7be1c272375d5077f3647c587f8033aa8c9275f840562", "metadata" : { - "palette" : { - "originalArgb8888" : [ -265674 ], - "convertedRgb565" : [ -122 ] - }, "tile" : { "width" : 32, "height" : 32, "paletteIndices" : "AQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAAAAAAAAAAABAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEAAAAAAAAAAAEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQAAAAAAAAAAAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAAAAAAAAAAABAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEAAAAAAAAAAAEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQAAAAAAAAAAAQEBAQEBAQEBAQEBAAAAAAAAAAAAAAAAAAAAAAAAAAABAQEBAQEBAQEBAQEAAAAAAAAAAAAAAAAAAAAAAAAAAAEBAQEBAQEBAQEBAQAAAAAAAAAAAAAAAAAAAAAAAAAAAQEBAQEBAQEBAQEBAAAAAAAAAAAAAAAAAAAAAAAAAAABAQEBAQEBAQEBAQEAAAAAAAAAAAAAAAAAAAAAAAAAAAEBAQEBAQEBAQEBAQAAAAAAAAAAAAAAAAAAAAAAAAAAAQEBAQEBAQEBAQEBAAAAAAAAAAAAAAAAAAAAAAAAAAABAQEBAQEBAQEBAQEAAAAAAAAAAAAAAAAAAAAAAAAAAAEBAQEBAQEBAQEBAQAAAAAAAAAAAAAAAAAAAQEBAQEBAQEBAQEBAQEBAQEBAAAAAAAAAAAAAAAAAAABAQEBAQEBAQEBAQEBAQEBAQEAAAAAAAAAAAAAAAAAAAEBAQEBAQEBAQEBAQEBAQEBAQAAAAAAAAAAAAAAAAAAAQEBAQEBAQEBAQEBAAAAAAAAAAAAAAAAAAAAAAAAAAABAQEBAQEBAQEBAQEAAAAAAAAAAAAAAAAAAAAAAAAAAAEBAQEBAQEBAQEBAQAAAAAAAAAAAAAAAAAAAQEBAQEBAQEBAQEBAQEBAQEBAAAAAAAAAAAAAAAAAAABAQEBAQEBAQEBAQEBAQEBAQEAAAAAAAAAAAAAAAAAAAEBAQEBAQEBAQEBAQEBAQEBAQAAAAAAAAAAAAAAAAAAAQEBAQEBAQEBAQEBAQEBAQEBAAAAAAAAAAAAAAAAAAABAQEBAQEBAQEBAQEBAQEBAQEAAAAAAAAAAAAAAAAAAAEBAQEBAQEBAQEBAQ==" + }, + "palette" : { + "originalArgb8888" : [ -265674 ], + "convertedRgb565" : [ -122 ] } }, "diagnostics" : [ ] @@ -708,14 +708,14 @@ "last_modified" : 1774359772453, "fingerprint" : "eeb7cc665386299403b7be1c272375d5077f3647c587f8033aa8c9275f840562", "metadata" : { - "palette" : { - "originalArgb8888" : [ -265674 ], - "convertedRgb565" : [ -122 ] - }, "tile" : { "width" : 32, "height" : 32, "paletteIndices" : "AQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAAAAAAAAAAABAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEAAAAAAAAAAAEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQAAAAAAAAAAAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAAAAAAAAAAABAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEAAAAAAAAAAAEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQAAAAAAAAAAAQEBAQEBAQEBAQEBAAAAAAAAAAAAAAAAAAAAAAAAAAABAQEBAQEBAQEBAQEAAAAAAAAAAAAAAAAAAAAAAAAAAAEBAQEBAQEBAQEBAQAAAAAAAAAAAAAAAAAAAAAAAAAAAQEBAQEBAQEBAQEBAAAAAAAAAAAAAAAAAAAAAAAAAAABAQEBAQEBAQEBAQEAAAAAAAAAAAAAAAAAAAAAAAAAAAEBAQEBAQEBAQEBAQAAAAAAAAAAAAAAAAAAAAAAAAAAAQEBAQEBAQEBAQEBAAAAAAAAAAAAAAAAAAAAAAAAAAABAQEBAQEBAQEBAQEAAAAAAAAAAAAAAAAAAAAAAAAAAAEBAQEBAQEBAQEBAQAAAAAAAAAAAAAAAAAAAQEBAQEBAQEBAQEBAQEBAQEBAAAAAAAAAAAAAAAAAAABAQEBAQEBAQEBAQEBAQEBAQEAAAAAAAAAAAAAAAAAAAEBAQEBAQEBAQEBAQEBAQEBAQAAAAAAAAAAAAAAAAAAAQEBAQEBAQEBAQEBAAAAAAAAAAAAAAAAAAAAAAAAAAABAQEBAQEBAQEBAQEAAAAAAAAAAAAAAAAAAAAAAAAAAAEBAQEBAQEBAQEBAQAAAAAAAAAAAAAAAAAAAQEBAQEBAQEBAQEBAQEBAQEBAAAAAAAAAAAAAAAAAAABAQEBAQEBAQEBAQEBAQEBAQEAAAAAAAAAAAAAAAAAAAEBAQEBAQEBAQEBAQEBAQEBAQAAAAAAAAAAAAAAAAAAAQEBAQEBAQEBAQEBAQEBAQEBAAAAAAAAAAAAAAAAAAABAQEBAQEBAQEBAQEBAQEBAQEAAAAAAAAAAAAAAAAAAAEBAQEBAQEBAQEBAQ==" + }, + "palette" : { + "originalArgb8888" : [ -265674 ], + "convertedRgb565" : [ -122 ] } }, "diagnostics" : [ ] @@ -726,14 +726,14 @@ "last_modified" : 1774359772454, "fingerprint" : "eeb7cc665386299403b7be1c272375d5077f3647c587f8033aa8c9275f840562", "metadata" : { - "palette" : { - "originalArgb8888" : [ -265674 ], - "convertedRgb565" : [ -122 ] - }, "tile" : { "width" : 32, "height" : 32, "paletteIndices" : "AQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAAAAAAAAAAABAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEAAAAAAAAAAAEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQAAAAAAAAAAAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAAAAAAAAAAABAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEAAAAAAAAAAAEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQAAAAAAAAAAAQEBAQEBAQEBAQEBAAAAAAAAAAAAAAAAAAAAAAAAAAABAQEBAQEBAQEBAQEAAAAAAAAAAAAAAAAAAAAAAAAAAAEBAQEBAQEBAQEBAQAAAAAAAAAAAAAAAAAAAAAAAAAAAQEBAQEBAQEBAQEBAAAAAAAAAAAAAAAAAAAAAAAAAAABAQEBAQEBAQEBAQEAAAAAAAAAAAAAAAAAAAAAAAAAAAEBAQEBAQEBAQEBAQAAAAAAAAAAAAAAAAAAAAAAAAAAAQEBAQEBAQEBAQEBAAAAAAAAAAAAAAAAAAAAAAAAAAABAQEBAQEBAQEBAQEAAAAAAAAAAAAAAAAAAAAAAAAAAAEBAQEBAQEBAQEBAQAAAAAAAAAAAAAAAAAAAQEBAQEBAQEBAQEBAQEBAQEBAAAAAAAAAAAAAAAAAAABAQEBAQEBAQEBAQEBAQEBAQEAAAAAAAAAAAAAAAAAAAEBAQEBAQEBAQEBAQEBAQEBAQAAAAAAAAAAAAAAAAAAAQEBAQEBAQEBAQEBAAAAAAAAAAAAAAAAAAAAAAAAAAABAQEBAQEBAQEBAQEAAAAAAAAAAAAAAAAAAAAAAAAAAAEBAQEBAQEBAQEBAQAAAAAAAAAAAAAAAAAAAQEBAQEBAQEBAQEBAQEBAQEBAAAAAAAAAAAAAAAAAAABAQEBAQEBAQEBAQEBAQEBAQEAAAAAAAAAAAAAAAAAAAEBAQEBAQEBAQEBAQEBAQEBAQAAAAAAAAAAAAAAAAAAAQEBAQEBAQEBAQEBAQEBAQEBAAAAAAAAAAAAAAAAAAABAQEBAQEBAQEBAQEBAQEBAQEAAAAAAAAAAAAAAAAAAAEBAQEBAQEBAQEBAQ==" + }, + "palette" : { + "originalArgb8888" : [ -265674 ], + "convertedRgb565" : [ -122 ] } }, "diagnostics" : [ ] @@ -744,14 +744,14 @@ "last_modified" : 1774359772455, "fingerprint" : "eeb7cc665386299403b7be1c272375d5077f3647c587f8033aa8c9275f840562", "metadata" : { - "palette" : { - "originalArgb8888" : [ -265674 ], - "convertedRgb565" : [ -122 ] - }, "tile" : { "width" : 32, "height" : 32, "paletteIndices" : "AQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAAAAAAAAAAABAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEAAAAAAAAAAAEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQAAAAAAAAAAAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAAAAAAAAAAABAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEAAAAAAAAAAAEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQAAAAAAAAAAAQEBAQEBAQEBAQEBAAAAAAAAAAAAAAAAAAAAAAAAAAABAQEBAQEBAQEBAQEAAAAAAAAAAAAAAAAAAAAAAAAAAAEBAQEBAQEBAQEBAQAAAAAAAAAAAAAAAAAAAAAAAAAAAQEBAQEBAQEBAQEBAAAAAAAAAAAAAAAAAAAAAAAAAAABAQEBAQEBAQEBAQEAAAAAAAAAAAAAAAAAAAAAAAAAAAEBAQEBAQEBAQEBAQAAAAAAAAAAAAAAAAAAAAAAAAAAAQEBAQEBAQEBAQEBAAAAAAAAAAAAAAAAAAAAAAAAAAABAQEBAQEBAQEBAQEAAAAAAAAAAAAAAAAAAAAAAAAAAAEBAQEBAQEBAQEBAQAAAAAAAAAAAAAAAAAAAQEBAQEBAQEBAQEBAQEBAQEBAAAAAAAAAAAAAAAAAAABAQEBAQEBAQEBAQEBAQEBAQEAAAAAAAAAAAAAAAAAAAEBAQEBAQEBAQEBAQEBAQEBAQAAAAAAAAAAAAAAAAAAAQEBAQEBAQEBAQEBAAAAAAAAAAAAAAAAAAAAAAAAAAABAQEBAQEBAQEBAQEAAAAAAAAAAAAAAAAAAAAAAAAAAAEBAQEBAQEBAQEBAQAAAAAAAAAAAAAAAAAAAQEBAQEBAQEBAQEBAQEBAQEBAAAAAAAAAAAAAAAAAAABAQEBAQEBAQEBAQEBAQEBAQEAAAAAAAAAAAAAAAAAAAEBAQEBAQEBAQEBAQEBAQEBAQAAAAAAAAAAAAAAAAAAAQEBAQEBAQEBAQEBAQEBAQEBAAAAAAAAAAAAAAAAAAABAQEBAQEBAQEBAQEBAQEBAQEAAAAAAAAAAAAAAAAAAAEBAQEBAQEBAQEBAQ==" + }, + "palette" : { + "originalArgb8888" : [ -265674 ], + "convertedRgb565" : [ -122 ] } }, "diagnostics" : [ ] @@ -762,14 +762,14 @@ "last_modified" : 1774359772456, "fingerprint" : "eeb7cc665386299403b7be1c272375d5077f3647c587f8033aa8c9275f840562", "metadata" : { - "palette" : { - "originalArgb8888" : [ -265674 ], - "convertedRgb565" : [ -122 ] - }, "tile" : { "width" : 32, "height" : 32, "paletteIndices" : "AQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAAAAAAAAAAABAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEAAAAAAAAAAAEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQAAAAAAAAAAAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAAAAAAAAAAABAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEAAAAAAAAAAAEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQAAAAAAAAAAAQEBAQEBAQEBAQEBAAAAAAAAAAAAAAAAAAAAAAAAAAABAQEBAQEBAQEBAQEAAAAAAAAAAAAAAAAAAAAAAAAAAAEBAQEBAQEBAQEBAQAAAAAAAAAAAAAAAAAAAAAAAAAAAQEBAQEBAQEBAQEBAAAAAAAAAAAAAAAAAAAAAAAAAAABAQEBAQEBAQEBAQEAAAAAAAAAAAAAAAAAAAAAAAAAAAEBAQEBAQEBAQEBAQAAAAAAAAAAAAAAAAAAAAAAAAAAAQEBAQEBAQEBAQEBAAAAAAAAAAAAAAAAAAAAAAAAAAABAQEBAQEBAQEBAQEAAAAAAAAAAAAAAAAAAAAAAAAAAAEBAQEBAQEBAQEBAQAAAAAAAAAAAAAAAAAAAQEBAQEBAQEBAQEBAQEBAQEBAAAAAAAAAAAAAAAAAAABAQEBAQEBAQEBAQEBAQEBAQEAAAAAAAAAAAAAAAAAAAEBAQEBAQEBAQEBAQEBAQEBAQAAAAAAAAAAAAAAAAAAAQEBAQEBAQEBAQEBAAAAAAAAAAAAAAAAAAAAAAAAAAABAQEBAQEBAQEBAQEAAAAAAAAAAAAAAAAAAAAAAAAAAAEBAQEBAQEBAQEBAQAAAAAAAAAAAAAAAAAAAQEBAQEBAQEBAQEBAQEBAQEBAAAAAAAAAAAAAAAAAAABAQEBAQEBAQEBAQEBAQEBAQEAAAAAAAAAAAAAAAAAAAEBAQEBAQEBAQEBAQEBAQEBAQAAAAAAAAAAAAAAAAAAAQEBAQEBAQEBAQEBAQEBAQEBAAAAAAAAAAAAAAAAAAABAQEBAQEBAQEBAQEBAQEBAQEAAAAAAAAAAAAAAAAAAAEBAQEBAQEBAQEBAQ==" + }, + "palette" : { + "originalArgb8888" : [ -265674 ], + "convertedRgb565" : [ -122 ] } }, "diagnostics" : [ ] @@ -780,14 +780,14 @@ "last_modified" : 1774359772458, "fingerprint" : "eeb7cc665386299403b7be1c272375d5077f3647c587f8033aa8c9275f840562", "metadata" : { - "palette" : { - "originalArgb8888" : [ -265674 ], - "convertedRgb565" : [ -122 ] - }, "tile" : { "width" : 32, "height" : 32, "paletteIndices" : "AQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAAAAAAAAAAABAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEAAAAAAAAAAAEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQAAAAAAAAAAAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAAAAAAAAAAABAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEAAAAAAAAAAAEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQAAAAAAAAAAAQEBAQEBAQEBAQEBAAAAAAAAAAAAAAAAAAAAAAAAAAABAQEBAQEBAQEBAQEAAAAAAAAAAAAAAAAAAAAAAAAAAAEBAQEBAQEBAQEBAQAAAAAAAAAAAAAAAAAAAAAAAAAAAQEBAQEBAQEBAQEBAAAAAAAAAAAAAAAAAAAAAAAAAAABAQEBAQEBAQEBAQEAAAAAAAAAAAAAAAAAAAAAAAAAAAEBAQEBAQEBAQEBAQAAAAAAAAAAAAAAAAAAAAAAAAAAAQEBAQEBAQEBAQEBAAAAAAAAAAAAAAAAAAAAAAAAAAABAQEBAQEBAQEBAQEAAAAAAAAAAAAAAAAAAAAAAAAAAAEBAQEBAQEBAQEBAQAAAAAAAAAAAAAAAAAAAQEBAQEBAQEBAQEBAQEBAQEBAAAAAAAAAAAAAAAAAAABAQEBAQEBAQEBAQEBAQEBAQEAAAAAAAAAAAAAAAAAAAEBAQEBAQEBAQEBAQEBAQEBAQAAAAAAAAAAAAAAAAAAAQEBAQEBAQEBAQEBAAAAAAAAAAAAAAAAAAAAAAAAAAABAQEBAQEBAQEBAQEAAAAAAAAAAAAAAAAAAAAAAAAAAAEBAQEBAQEBAQEBAQAAAAAAAAAAAAAAAAAAAQEBAQEBAQEBAQEBAQEBAQEBAAAAAAAAAAAAAAAAAAABAQEBAQEBAQEBAQEBAQEBAQEAAAAAAAAAAAAAAAAAAAEBAQEBAQEBAQEBAQEBAQEBAQAAAAAAAAAAAAAAAAAAAQEBAQEBAQEBAQEBAQEBAQEBAAAAAAAAAAAAAAAAAAABAQEBAQEBAQEBAQEBAQEBAQEAAAAAAAAAAAAAAAAAAAEBAQEBAQEBAQEBAQ==" + }, + "palette" : { + "originalArgb8888" : [ -265674 ], + "convertedRgb565" : [ -122 ] } }, "diagnostics" : [ ] @@ -798,14 +798,14 @@ "last_modified" : 1774359772459, "fingerprint" : "eeb7cc665386299403b7be1c272375d5077f3647c587f8033aa8c9275f840562", "metadata" : { - "palette" : { - "originalArgb8888" : [ -265674 ], - "convertedRgb565" : [ -122 ] - }, "tile" : { "width" : 32, "height" : 32, "paletteIndices" : "AQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAAAAAAAAAAABAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEAAAAAAAAAAAEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQAAAAAAAAAAAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAAAAAAAAAAABAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEAAAAAAAAAAAEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQAAAAAAAAAAAQEBAQEBAQEBAQEBAAAAAAAAAAAAAAAAAAAAAAAAAAABAQEBAQEBAQEBAQEAAAAAAAAAAAAAAAAAAAAAAAAAAAEBAQEBAQEBAQEBAQAAAAAAAAAAAAAAAAAAAAAAAAAAAQEBAQEBAQEBAQEBAAAAAAAAAAAAAAAAAAAAAAAAAAABAQEBAQEBAQEBAQEAAAAAAAAAAAAAAAAAAAAAAAAAAAEBAQEBAQEBAQEBAQAAAAAAAAAAAAAAAAAAAAAAAAAAAQEBAQEBAQEBAQEBAAAAAAAAAAAAAAAAAAAAAAAAAAABAQEBAQEBAQEBAQEAAAAAAAAAAAAAAAAAAAAAAAAAAAEBAQEBAQEBAQEBAQAAAAAAAAAAAAAAAAAAAQEBAQEBAQEBAQEBAQEBAQEBAAAAAAAAAAAAAAAAAAABAQEBAQEBAQEBAQEBAQEBAQEAAAAAAAAAAAAAAAAAAAEBAQEBAQEBAQEBAQEBAQEBAQAAAAAAAAAAAAAAAAAAAQEBAQEBAQEBAQEBAAAAAAAAAAAAAAAAAAAAAAAAAAABAQEBAQEBAQEBAQEAAAAAAAAAAAAAAAAAAAAAAAAAAAEBAQEBAQEBAQEBAQAAAAAAAAAAAAAAAAAAAQEBAQEBAQEBAQEBAQEBAQEBAAAAAAAAAAAAAAAAAAABAQEBAQEBAQEBAQEBAQEBAQEAAAAAAAAAAAAAAAAAAAEBAQEBAQEBAQEBAQEBAQEBAQAAAAAAAAAAAAAAAAAAAQEBAQEBAQEBAQEBAQEBAQEBAAAAAAAAAAAAAAAAAAABAQEBAQEBAQEBAQEBAQEBAQEAAAAAAAAAAAAAAAAAAAEBAQEBAQEBAQEBAQ==" + }, + "palette" : { + "originalArgb8888" : [ -265674 ], + "convertedRgb565" : [ -122 ] } }, "diagnostics" : [ ] @@ -816,14 +816,14 @@ "last_modified" : 1774359772460, "fingerprint" : "eeb7cc665386299403b7be1c272375d5077f3647c587f8033aa8c9275f840562", "metadata" : { - "palette" : { - "originalArgb8888" : [ -265674 ], - "convertedRgb565" : [ -122 ] - }, "tile" : { "width" : 32, "height" : 32, "paletteIndices" : "AQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAAAAAAAAAAABAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEAAAAAAAAAAAEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQAAAAAAAAAAAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAAAAAAAAAAABAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEAAAAAAAAAAAEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQAAAAAAAAAAAQEBAQEBAQEBAQEBAAAAAAAAAAAAAAAAAAAAAAAAAAABAQEBAQEBAQEBAQEAAAAAAAAAAAAAAAAAAAAAAAAAAAEBAQEBAQEBAQEBAQAAAAAAAAAAAAAAAAAAAAAAAAAAAQEBAQEBAQEBAQEBAAAAAAAAAAAAAAAAAAAAAAAAAAABAQEBAQEBAQEBAQEAAAAAAAAAAAAAAAAAAAAAAAAAAAEBAQEBAQEBAQEBAQAAAAAAAAAAAAAAAAAAAAAAAAAAAQEBAQEBAQEBAQEBAAAAAAAAAAAAAAAAAAAAAAAAAAABAQEBAQEBAQEBAQEAAAAAAAAAAAAAAAAAAAAAAAAAAAEBAQEBAQEBAQEBAQAAAAAAAAAAAAAAAAAAAQEBAQEBAQEBAQEBAQEBAQEBAAAAAAAAAAAAAAAAAAABAQEBAQEBAQEBAQEBAQEBAQEAAAAAAAAAAAAAAAAAAAEBAQEBAQEBAQEBAQEBAQEBAQAAAAAAAAAAAAAAAAAAAQEBAQEBAQEBAQEBAAAAAAAAAAAAAAAAAAAAAAAAAAABAQEBAQEBAQEBAQEAAAAAAAAAAAAAAAAAAAAAAAAAAAEBAQEBAQEBAQEBAQAAAAAAAAAAAAAAAAAAAQEBAQEBAQEBAQEBAQEBAQEBAAAAAAAAAAAAAAAAAAABAQEBAQEBAQEBAQEBAQEBAQEAAAAAAAAAAAAAAAAAAAEBAQEBAQEBAQEBAQEBAQEBAQAAAAAAAAAAAAAAAAAAAQEBAQEBAQEBAQEBAQEBAQEBAAAAAAAAAAAAAAAAAAABAQEBAQEBAQEBAQEBAQEBAQEAAAAAAAAAAAAAAAAAAAEBAQEBAQEBAQEBAQ==" + }, + "palette" : { + "originalArgb8888" : [ -265674 ], + "convertedRgb565" : [ -122 ] } }, "diagnostics" : [ ] @@ -834,14 +834,14 @@ "last_modified" : 1774359772461, "fingerprint" : "eeb7cc665386299403b7be1c272375d5077f3647c587f8033aa8c9275f840562", "metadata" : { - "palette" : { - "originalArgb8888" : [ -265674 ], - "convertedRgb565" : [ -122 ] - }, "tile" : { "width" : 32, "height" : 32, "paletteIndices" : "AQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAAAAAAAAAAABAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEAAAAAAAAAAAEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQAAAAAAAAAAAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAAAAAAAAAAABAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEAAAAAAAAAAAEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQAAAAAAAAAAAQEBAQEBAQEBAQEBAAAAAAAAAAAAAAAAAAAAAAAAAAABAQEBAQEBAQEBAQEAAAAAAAAAAAAAAAAAAAAAAAAAAAEBAQEBAQEBAQEBAQAAAAAAAAAAAAAAAAAAAAAAAAAAAQEBAQEBAQEBAQEBAAAAAAAAAAAAAAAAAAAAAAAAAAABAQEBAQEBAQEBAQEAAAAAAAAAAAAAAAAAAAAAAAAAAAEBAQEBAQEBAQEBAQAAAAAAAAAAAAAAAAAAAAAAAAAAAQEBAQEBAQEBAQEBAAAAAAAAAAAAAAAAAAAAAAAAAAABAQEBAQEBAQEBAQEAAAAAAAAAAAAAAAAAAAAAAAAAAAEBAQEBAQEBAQEBAQAAAAAAAAAAAAAAAAAAAQEBAQEBAQEBAQEBAQEBAQEBAAAAAAAAAAAAAAAAAAABAQEBAQEBAQEBAQEBAQEBAQEAAAAAAAAAAAAAAAAAAAEBAQEBAQEBAQEBAQEBAQEBAQAAAAAAAAAAAAAAAAAAAQEBAQEBAQEBAQEBAAAAAAAAAAAAAAAAAAAAAAAAAAABAQEBAQEBAQEBAQEAAAAAAAAAAAAAAAAAAAAAAAAAAAEBAQEBAQEBAQEBAQAAAAAAAAAAAAAAAAAAAQEBAQEBAQEBAQEBAQEBAQEBAAAAAAAAAAAAAAAAAAABAQEBAQEBAQEBAQEBAQEBAQEAAAAAAAAAAAAAAAAAAAEBAQEBAQEBAQEBAQEBAQEBAQAAAAAAAAAAAAAAAAAAAQEBAQEBAQEBAQEBAQEBAQEBAAAAAAAAAAAAAAAAAAABAQEBAQEBAQEBAQEBAQEBAQEAAAAAAAAAAAAAAAAAAAEBAQEBAQEBAQEBAQ==" + }, + "palette" : { + "originalArgb8888" : [ -265674 ], + "convertedRgb565" : [ -122 ] } }, "diagnostics" : [ ] @@ -852,14 +852,14 @@ "last_modified" : 1774359772463, "fingerprint" : "eeb7cc665386299403b7be1c272375d5077f3647c587f8033aa8c9275f840562", "metadata" : { - "palette" : { - "originalArgb8888" : [ -265674 ], - "convertedRgb565" : [ -122 ] - }, "tile" : { "width" : 32, "height" : 32, "paletteIndices" : "AQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAAAAAAAAAAABAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEAAAAAAAAAAAEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQAAAAAAAAAAAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAAAAAAAAAAABAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEAAAAAAAAAAAEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQAAAAAAAAAAAQEBAQEBAQEBAQEBAAAAAAAAAAAAAAAAAAAAAAAAAAABAQEBAQEBAQEBAQEAAAAAAAAAAAAAAAAAAAAAAAAAAAEBAQEBAQEBAQEBAQAAAAAAAAAAAAAAAAAAAAAAAAAAAQEBAQEBAQEBAQEBAAAAAAAAAAAAAAAAAAAAAAAAAAABAQEBAQEBAQEBAQEAAAAAAAAAAAAAAAAAAAAAAAAAAAEBAQEBAQEBAQEBAQAAAAAAAAAAAAAAAAAAAAAAAAAAAQEBAQEBAQEBAQEBAAAAAAAAAAAAAAAAAAAAAAAAAAABAQEBAQEBAQEBAQEAAAAAAAAAAAAAAAAAAAAAAAAAAAEBAQEBAQEBAQEBAQAAAAAAAAAAAAAAAAAAAQEBAQEBAQEBAQEBAQEBAQEBAAAAAAAAAAAAAAAAAAABAQEBAQEBAQEBAQEBAQEBAQEAAAAAAAAAAAAAAAAAAAEBAQEBAQEBAQEBAQEBAQEBAQAAAAAAAAAAAAAAAAAAAQEBAQEBAQEBAQEBAAAAAAAAAAAAAAAAAAAAAAAAAAABAQEBAQEBAQEBAQEAAAAAAAAAAAAAAAAAAAAAAAAAAAEBAQEBAQEBAQEBAQAAAAAAAAAAAAAAAAAAAQEBAQEBAQEBAQEBAQEBAQEBAAAAAAAAAAAAAAAAAAABAQEBAQEBAQEBAQEBAQEBAQEAAAAAAAAAAAAAAAAAAAEBAQEBAQEBAQEBAQEBAQEBAQAAAAAAAAAAAAAAAAAAAQEBAQEBAQEBAQEBAQEBAQEBAAAAAAAAAAAAAAAAAAABAQEBAQEBAQEBAQEBAQEBAQEAAAAAAAAAAAAAAAAAAAEBAQEBAQEBAQEBAQ==" + }, + "palette" : { + "originalArgb8888" : [ -265674 ], + "convertedRgb565" : [ -122 ] } }, "diagnostics" : [ ] @@ -870,14 +870,14 @@ "last_modified" : 1774359772464, "fingerprint" : "eeb7cc665386299403b7be1c272375d5077f3647c587f8033aa8c9275f840562", "metadata" : { - "palette" : { - "originalArgb8888" : [ -265674 ], - "convertedRgb565" : [ -122 ] - }, "tile" : { "width" : 32, "height" : 32, "paletteIndices" : "AQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAAAAAAAAAAABAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEAAAAAAAAAAAEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQAAAAAAAAAAAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAAAAAAAAAAABAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEAAAAAAAAAAAEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQAAAAAAAAAAAQEBAQEBAQEBAQEBAAAAAAAAAAAAAAAAAAAAAAAAAAABAQEBAQEBAQEBAQEAAAAAAAAAAAAAAAAAAAAAAAAAAAEBAQEBAQEBAQEBAQAAAAAAAAAAAAAAAAAAAAAAAAAAAQEBAQEBAQEBAQEBAAAAAAAAAAAAAAAAAAAAAAAAAAABAQEBAQEBAQEBAQEAAAAAAAAAAAAAAAAAAAAAAAAAAAEBAQEBAQEBAQEBAQAAAAAAAAAAAAAAAAAAAAAAAAAAAQEBAQEBAQEBAQEBAAAAAAAAAAAAAAAAAAAAAAAAAAABAQEBAQEBAQEBAQEAAAAAAAAAAAAAAAAAAAAAAAAAAAEBAQEBAQEBAQEBAQAAAAAAAAAAAAAAAAAAAQEBAQEBAQEBAQEBAQEBAQEBAAAAAAAAAAAAAAAAAAABAQEBAQEBAQEBAQEBAQEBAQEAAAAAAAAAAAAAAAAAAAEBAQEBAQEBAQEBAQEBAQEBAQAAAAAAAAAAAAAAAAAAAQEBAQEBAQEBAQEBAAAAAAAAAAAAAAAAAAAAAAAAAAABAQEBAQEBAQEBAQEAAAAAAAAAAAAAAAAAAAAAAAAAAAEBAQEBAQEBAQEBAQAAAAAAAAAAAAAAAAAAAQEBAQEBAQEBAQEBAQEBAQEBAAAAAAAAAAAAAAAAAAABAQEBAQEBAQEBAQEBAQEBAQEAAAAAAAAAAAAAAAAAAAEBAQEBAQEBAQEBAQEBAQEBAQAAAAAAAAAAAAAAAAAAAQEBAQEBAQEBAQEBAQEBAQEBAAAAAAAAAAAAAAAAAAABAQEBAQEBAQEBAQEBAQEBAQEAAAAAAAAAAAAAAAAAAAEBAQEBAQEBAQEBAQ==" + }, + "palette" : { + "originalArgb8888" : [ -265674 ], + "convertedRgb565" : [ -122 ] } }, "diagnostics" : [ ] @@ -888,14 +888,14 @@ "last_modified" : 1774359772465, "fingerprint" : "eeb7cc665386299403b7be1c272375d5077f3647c587f8033aa8c9275f840562", "metadata" : { - "palette" : { - "originalArgb8888" : [ -265674 ], - "convertedRgb565" : [ -122 ] - }, "tile" : { "width" : 32, "height" : 32, "paletteIndices" : "AQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAAAAAAAAAAABAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEAAAAAAAAAAAEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQAAAAAAAAAAAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAAAAAAAAAAABAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEAAAAAAAAAAAEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQAAAAAAAAAAAQEBAQEBAQEBAQEBAAAAAAAAAAAAAAAAAAAAAAAAAAABAQEBAQEBAQEBAQEAAAAAAAAAAAAAAAAAAAAAAAAAAAEBAQEBAQEBAQEBAQAAAAAAAAAAAAAAAAAAAAAAAAAAAQEBAQEBAQEBAQEBAAAAAAAAAAAAAAAAAAAAAAAAAAABAQEBAQEBAQEBAQEAAAAAAAAAAAAAAAAAAAAAAAAAAAEBAQEBAQEBAQEBAQAAAAAAAAAAAAAAAAAAAAAAAAAAAQEBAQEBAQEBAQEBAAAAAAAAAAAAAAAAAAAAAAAAAAABAQEBAQEBAQEBAQEAAAAAAAAAAAAAAAAAAAAAAAAAAAEBAQEBAQEBAQEBAQAAAAAAAAAAAAAAAAAAAQEBAQEBAQEBAQEBAQEBAQEBAAAAAAAAAAAAAAAAAAABAQEBAQEBAQEBAQEBAQEBAQEAAAAAAAAAAAAAAAAAAAEBAQEBAQEBAQEBAQEBAQEBAQAAAAAAAAAAAAAAAAAAAQEBAQEBAQEBAQEBAAAAAAAAAAAAAAAAAAAAAAAAAAABAQEBAQEBAQEBAQEAAAAAAAAAAAAAAAAAAAAAAAAAAAEBAQEBAQEBAQEBAQAAAAAAAAAAAAAAAAAAAQEBAQEBAQEBAQEBAQEBAQEBAAAAAAAAAAAAAAAAAAABAQEBAQEBAQEBAQEBAQEBAQEAAAAAAAAAAAAAAAAAAAEBAQEBAQEBAQEBAQEBAQEBAQAAAAAAAAAAAAAAAAAAAQEBAQEBAQEBAQEBAQEBAQEBAAAAAAAAAAAAAAAAAAABAQEBAQEBAQEBAQEBAQEBAQEAAAAAAAAAAAAAAAAAAAEBAQEBAQEBAQEBAQ==" + }, + "palette" : { + "originalArgb8888" : [ -265674 ], + "convertedRgb565" : [ -122 ] } }, "diagnostics" : [ ] @@ -906,14 +906,14 @@ "last_modified" : 1774359772467, "fingerprint" : "eeb7cc665386299403b7be1c272375d5077f3647c587f8033aa8c9275f840562", "metadata" : { - "palette" : { - "originalArgb8888" : [ -265674 ], - "convertedRgb565" : [ -122 ] - }, "tile" : { "width" : 32, "height" : 32, "paletteIndices" : "AQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAAAAAAAAAAABAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEAAAAAAAAAAAEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQAAAAAAAAAAAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAAAAAAAAAAABAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEAAAAAAAAAAAEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQAAAAAAAAAAAQEBAQEBAQEBAQEBAAAAAAAAAAAAAAAAAAAAAAAAAAABAQEBAQEBAQEBAQEAAAAAAAAAAAAAAAAAAAAAAAAAAAEBAQEBAQEBAQEBAQAAAAAAAAAAAAAAAAAAAAAAAAAAAQEBAQEBAQEBAQEBAAAAAAAAAAAAAAAAAAAAAAAAAAABAQEBAQEBAQEBAQEAAAAAAAAAAAAAAAAAAAAAAAAAAAEBAQEBAQEBAQEBAQAAAAAAAAAAAAAAAAAAAAAAAAAAAQEBAQEBAQEBAQEBAAAAAAAAAAAAAAAAAAAAAAAAAAABAQEBAQEBAQEBAQEAAAAAAAAAAAAAAAAAAAAAAAAAAAEBAQEBAQEBAQEBAQAAAAAAAAAAAAAAAAAAAQEBAQEBAQEBAQEBAQEBAQEBAAAAAAAAAAAAAAAAAAABAQEBAQEBAQEBAQEBAQEBAQEAAAAAAAAAAAAAAAAAAAEBAQEBAQEBAQEBAQEBAQEBAQAAAAAAAAAAAAAAAAAAAQEBAQEBAQEBAQEBAAAAAAAAAAAAAAAAAAAAAAAAAAABAQEBAQEBAQEBAQEAAAAAAAAAAAAAAAAAAAAAAAAAAAEBAQEBAQEBAQEBAQAAAAAAAAAAAAAAAAAAAQEBAQEBAQEBAQEBAQEBAQEBAAAAAAAAAAAAAAAAAAABAQEBAQEBAQEBAQEBAQEBAQEAAAAAAAAAAAAAAAAAAAEBAQEBAQEBAQEBAQEBAQEBAQAAAAAAAAAAAAAAAAAAAQEBAQEBAQEBAQEBAQEBAQEBAAAAAAAAAAAAAAAAAAABAQEBAQEBAQEBAQEBAQEBAQEAAAAAAAAAAAAAAAAAAAEBAQEBAQEBAQEBAQ==" + }, + "palette" : { + "originalArgb8888" : [ -265674 ], + "convertedRgb565" : [ -122 ] } }, "diagnostics" : [ ] @@ -924,14 +924,14 @@ "last_modified" : 1774359772468, "fingerprint" : "eeb7cc665386299403b7be1c272375d5077f3647c587f8033aa8c9275f840562", "metadata" : { - "palette" : { - "originalArgb8888" : [ -265674 ], - "convertedRgb565" : [ -122 ] - }, "tile" : { "width" : 32, "height" : 32, "paletteIndices" : "AQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAAAAAAAAAAABAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEAAAAAAAAAAAEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQAAAAAAAAAAAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAAAAAAAAAAABAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEAAAAAAAAAAAEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQAAAAAAAAAAAQEBAQEBAQEBAQEBAAAAAAAAAAAAAAAAAAAAAAAAAAABAQEBAQEBAQEBAQEAAAAAAAAAAAAAAAAAAAAAAAAAAAEBAQEBAQEBAQEBAQAAAAAAAAAAAAAAAAAAAAAAAAAAAQEBAQEBAQEBAQEBAAAAAAAAAAAAAAAAAAAAAAAAAAABAQEBAQEBAQEBAQEAAAAAAAAAAAAAAAAAAAAAAAAAAAEBAQEBAQEBAQEBAQAAAAAAAAAAAAAAAAAAAAAAAAAAAQEBAQEBAQEBAQEBAAAAAAAAAAAAAAAAAAAAAAAAAAABAQEBAQEBAQEBAQEAAAAAAAAAAAAAAAAAAAAAAAAAAAEBAQEBAQEBAQEBAQAAAAAAAAAAAAAAAAAAAQEBAQEBAQEBAQEBAQEBAQEBAAAAAAAAAAAAAAAAAAABAQEBAQEBAQEBAQEBAQEBAQEAAAAAAAAAAAAAAAAAAAEBAQEBAQEBAQEBAQEBAQEBAQAAAAAAAAAAAAAAAAAAAQEBAQEBAQEBAQEBAAAAAAAAAAAAAAAAAAAAAAAAAAABAQEBAQEBAQEBAQEAAAAAAAAAAAAAAAAAAAAAAAAAAAEBAQEBAQEBAQEBAQAAAAAAAAAAAAAAAAAAAQEBAQEBAQEBAQEBAQEBAQEBAAAAAAAAAAAAAAAAAAABAQEBAQEBAQEBAQEBAQEBAQEAAAAAAAAAAAAAAAAAAAEBAQEBAQEBAQEBAQEBAQEBAQAAAAAAAAAAAAAAAAAAAQEBAQEBAQEBAQEBAQEBAQEBAAAAAAAAAAAAAAAAAAABAQEBAQEBAQEBAQEBAQEBAQEAAAAAAAAAAAAAAAAAAAEBAQEBAQEBAQEBAQ==" + }, + "palette" : { + "originalArgb8888" : [ -265674 ], + "convertedRgb565" : [ -122 ] } }, "diagnostics" : [ ] @@ -942,14 +942,14 @@ "last_modified" : 1774359772470, "fingerprint" : "eeb7cc665386299403b7be1c272375d5077f3647c587f8033aa8c9275f840562", "metadata" : { - "palette" : { - "originalArgb8888" : [ -265674 ], - "convertedRgb565" : [ -122 ] - }, "tile" : { "width" : 32, "height" : 32, "paletteIndices" : "AQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAAAAAAAAAAABAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEAAAAAAAAAAAEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQAAAAAAAAAAAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAAAAAAAAAAABAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEAAAAAAAAAAAEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQAAAAAAAAAAAQEBAQEBAQEBAQEBAAAAAAAAAAAAAAAAAAAAAAAAAAABAQEBAQEBAQEBAQEAAAAAAAAAAAAAAAAAAAAAAAAAAAEBAQEBAQEBAQEBAQAAAAAAAAAAAAAAAAAAAAAAAAAAAQEBAQEBAQEBAQEBAAAAAAAAAAAAAAAAAAAAAAAAAAABAQEBAQEBAQEBAQEAAAAAAAAAAAAAAAAAAAAAAAAAAAEBAQEBAQEBAQEBAQAAAAAAAAAAAAAAAAAAAAAAAAAAAQEBAQEBAQEBAQEBAAAAAAAAAAAAAAAAAAAAAAAAAAABAQEBAQEBAQEBAQEAAAAAAAAAAAAAAAAAAAAAAAAAAAEBAQEBAQEBAQEBAQAAAAAAAAAAAAAAAAAAAQEBAQEBAQEBAQEBAQEBAQEBAAAAAAAAAAAAAAAAAAABAQEBAQEBAQEBAQEBAQEBAQEAAAAAAAAAAAAAAAAAAAEBAQEBAQEBAQEBAQEBAQEBAQAAAAAAAAAAAAAAAAAAAQEBAQEBAQEBAQEBAAAAAAAAAAAAAAAAAAAAAAAAAAABAQEBAQEBAQEBAQEAAAAAAAAAAAAAAAAAAAAAAAAAAAEBAQEBAQEBAQEBAQAAAAAAAAAAAAAAAAAAAQEBAQEBAQEBAQEBAQEBAQEBAAAAAAAAAAAAAAAAAAABAQEBAQEBAQEBAQEBAQEBAQEAAAAAAAAAAAAAAAAAAAEBAQEBAQEBAQEBAQEBAQEBAQAAAAAAAAAAAAAAAAAAAQEBAQEBAQEBAQEBAQEBAQEBAAAAAAAAAAAAAAAAAAABAQEBAQEBAQEBAQEBAQEBAQEAAAAAAAAAAAAAAAAAAAEBAQEBAQEBAQEBAQ==" + }, + "palette" : { + "originalArgb8888" : [ -265674 ], + "convertedRgb565" : [ -122 ] } }, "diagnostics" : [ ] @@ -960,14 +960,14 @@ "last_modified" : 1774359772474, "fingerprint" : "eeb7cc665386299403b7be1c272375d5077f3647c587f8033aa8c9275f840562", "metadata" : { - "palette" : { - "originalArgb8888" : [ -265674 ], - "convertedRgb565" : [ -122 ] - }, "tile" : { "width" : 32, "height" : 32, "paletteIndices" : "AQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAAAAAAAAAAABAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEAAAAAAAAAAAEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQAAAAAAAAAAAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAAAAAAAAAAABAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEAAAAAAAAAAAEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQAAAAAAAAAAAQEBAQEBAQEBAQEBAAAAAAAAAAAAAAAAAAAAAAAAAAABAQEBAQEBAQEBAQEAAAAAAAAAAAAAAAAAAAAAAAAAAAEBAQEBAQEBAQEBAQAAAAAAAAAAAAAAAAAAAAAAAAAAAQEBAQEBAQEBAQEBAAAAAAAAAAAAAAAAAAAAAAAAAAABAQEBAQEBAQEBAQEAAAAAAAAAAAAAAAAAAAAAAAAAAAEBAQEBAQEBAQEBAQAAAAAAAAAAAAAAAAAAAAAAAAAAAQEBAQEBAQEBAQEBAAAAAAAAAAAAAAAAAAAAAAAAAAABAQEBAQEBAQEBAQEAAAAAAAAAAAAAAAAAAAAAAAAAAAEBAQEBAQEBAQEBAQAAAAAAAAAAAAAAAAAAAQEBAQEBAQEBAQEBAQEBAQEBAAAAAAAAAAAAAAAAAAABAQEBAQEBAQEBAQEBAQEBAQEAAAAAAAAAAAAAAAAAAAEBAQEBAQEBAQEBAQEBAQEBAQAAAAAAAAAAAAAAAAAAAQEBAQEBAQEBAQEBAAAAAAAAAAAAAAAAAAAAAAAAAAABAQEBAQEBAQEBAQEAAAAAAAAAAAAAAAAAAAAAAAAAAAEBAQEBAQEBAQEBAQAAAAAAAAAAAAAAAAAAAQEBAQEBAQEBAQEBAQEBAQEBAAAAAAAAAAAAAAAAAAABAQEBAQEBAQEBAQEBAQEBAQEAAAAAAAAAAAAAAAAAAAEBAQEBAQEBAQEBAQEBAQEBAQAAAAAAAAAAAAAAAAAAAQEBAQEBAQEBAQEBAQEBAQEBAAAAAAAAAAAAAAAAAAABAQEBAQEBAQEBAQEBAQEBAQEAAAAAAAAAAAAAAAAAAAEBAQEBAQEBAQEBAQ==" + }, + "palette" : { + "originalArgb8888" : [ -265674 ], + "convertedRgb565" : [ -122 ] } }, "diagnostics" : [ ] @@ -978,14 +978,14 @@ "last_modified" : 1774359772476, "fingerprint" : "eeb7cc665386299403b7be1c272375d5077f3647c587f8033aa8c9275f840562", "metadata" : { - "palette" : { - "originalArgb8888" : [ -265674 ], - "convertedRgb565" : [ -122 ] - }, "tile" : { "width" : 32, "height" : 32, "paletteIndices" : "AQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAAAAAAAAAAABAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEAAAAAAAAAAAEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQAAAAAAAAAAAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAAAAAAAAAAABAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEAAAAAAAAAAAEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQAAAAAAAAAAAQEBAQEBAQEBAQEBAAAAAAAAAAAAAAAAAAAAAAAAAAABAQEBAQEBAQEBAQEAAAAAAAAAAAAAAAAAAAAAAAAAAAEBAQEBAQEBAQEBAQAAAAAAAAAAAAAAAAAAAAAAAAAAAQEBAQEBAQEBAQEBAAAAAAAAAAAAAAAAAAAAAAAAAAABAQEBAQEBAQEBAQEAAAAAAAAAAAAAAAAAAAAAAAAAAAEBAQEBAQEBAQEBAQAAAAAAAAAAAAAAAAAAAAAAAAAAAQEBAQEBAQEBAQEBAAAAAAAAAAAAAAAAAAAAAAAAAAABAQEBAQEBAQEBAQEAAAAAAAAAAAAAAAAAAAAAAAAAAAEBAQEBAQEBAQEBAQAAAAAAAAAAAAAAAAAAAQEBAQEBAQEBAQEBAQEBAQEBAAAAAAAAAAAAAAAAAAABAQEBAQEBAQEBAQEBAQEBAQEAAAAAAAAAAAAAAAAAAAEBAQEBAQEBAQEBAQEBAQEBAQAAAAAAAAAAAAAAAAAAAQEBAQEBAQEBAQEBAAAAAAAAAAAAAAAAAAAAAAAAAAABAQEBAQEBAQEBAQEAAAAAAAAAAAAAAAAAAAAAAAAAAAEBAQEBAQEBAQEBAQAAAAAAAAAAAAAAAAAAAQEBAQEBAQEBAQEBAQEBAQEBAAAAAAAAAAAAAAAAAAABAQEBAQEBAQEBAQEBAQEBAQEAAAAAAAAAAAAAAAAAAAEBAQEBAQEBAQEBAQEBAQEBAQAAAAAAAAAAAAAAAAAAAQEBAQEBAQEBAQEBAQEBAQEBAAAAAAAAAAAAAAAAAAABAQEBAQEBAQEBAQEBAQEBAQEAAAAAAAAAAAAAAAAAAAEBAQEBAQEBAQEBAQ==" + }, + "palette" : { + "originalArgb8888" : [ -265674 ], + "convertedRgb565" : [ -122 ] } }, "diagnostics" : [ ] @@ -996,14 +996,14 @@ "last_modified" : 1774359772478, "fingerprint" : "eeb7cc665386299403b7be1c272375d5077f3647c587f8033aa8c9275f840562", "metadata" : { - "palette" : { - "originalArgb8888" : [ -265674 ], - "convertedRgb565" : [ -122 ] - }, "tile" : { "width" : 32, "height" : 32, "paletteIndices" : "AQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAAAAAAAAAAABAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEAAAAAAAAAAAEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQAAAAAAAAAAAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAAAAAAAAAAABAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEAAAAAAAAAAAEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQAAAAAAAAAAAQEBAQEBAQEBAQEBAAAAAAAAAAAAAAAAAAAAAAAAAAABAQEBAQEBAQEBAQEAAAAAAAAAAAAAAAAAAAAAAAAAAAEBAQEBAQEBAQEBAQAAAAAAAAAAAAAAAAAAAAAAAAAAAQEBAQEBAQEBAQEBAAAAAAAAAAAAAAAAAAAAAAAAAAABAQEBAQEBAQEBAQEAAAAAAAAAAAAAAAAAAAAAAAAAAAEBAQEBAQEBAQEBAQAAAAAAAAAAAAAAAAAAAAAAAAAAAQEBAQEBAQEBAQEBAAAAAAAAAAAAAAAAAAAAAAAAAAABAQEBAQEBAQEBAQEAAAAAAAAAAAAAAAAAAAAAAAAAAAEBAQEBAQEBAQEBAQAAAAAAAAAAAAAAAAAAAQEBAQEBAQEBAQEBAQEBAQEBAAAAAAAAAAAAAAAAAAABAQEBAQEBAQEBAQEBAQEBAQEAAAAAAAAAAAAAAAAAAAEBAQEBAQEBAQEBAQEBAQEBAQAAAAAAAAAAAAAAAAAAAQEBAQEBAQEBAQEBAAAAAAAAAAAAAAAAAAAAAAAAAAABAQEBAQEBAQEBAQEAAAAAAAAAAAAAAAAAAAAAAAAAAAEBAQEBAQEBAQEBAQAAAAAAAAAAAAAAAAAAAQEBAQEBAQEBAQEBAQEBAQEBAAAAAAAAAAAAAAAAAAABAQEBAQEBAQEBAQEBAQEBAQEAAAAAAAAAAAAAAAAAAAEBAQEBAQEBAQEBAQEBAQEBAQAAAAAAAAAAAAAAAAAAAQEBAQEBAQEBAQEBAQEBAQEBAAAAAAAAAAAAAAAAAAABAQEBAQEBAQEBAQEBAQEBAQEAAAAAAAAAAAAAAAAAAAEBAQEBAQEBAQEBAQ==" + }, + "palette" : { + "originalArgb8888" : [ -265674 ], + "convertedRgb565" : [ -122 ] } }, "diagnostics" : [ ] @@ -1014,14 +1014,14 @@ "last_modified" : 1774359772479, "fingerprint" : "eeb7cc665386299403b7be1c272375d5077f3647c587f8033aa8c9275f840562", "metadata" : { - "palette" : { - "originalArgb8888" : [ -265674 ], - "convertedRgb565" : [ -122 ] - }, "tile" : { "width" : 32, "height" : 32, "paletteIndices" : "AQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAAAAAAAAAAABAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEAAAAAAAAAAAEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQAAAAAAAAAAAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAAAAAAAAAAABAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEAAAAAAAAAAAEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQAAAAAAAAAAAQEBAQEBAQEBAQEBAAAAAAAAAAAAAAAAAAAAAAAAAAABAQEBAQEBAQEBAQEAAAAAAAAAAAAAAAAAAAAAAAAAAAEBAQEBAQEBAQEBAQAAAAAAAAAAAAAAAAAAAAAAAAAAAQEBAQEBAQEBAQEBAAAAAAAAAAAAAAAAAAAAAAAAAAABAQEBAQEBAQEBAQEAAAAAAAAAAAAAAAAAAAAAAAAAAAEBAQEBAQEBAQEBAQAAAAAAAAAAAAAAAAAAAAAAAAAAAQEBAQEBAQEBAQEBAAAAAAAAAAAAAAAAAAAAAAAAAAABAQEBAQEBAQEBAQEAAAAAAAAAAAAAAAAAAAAAAAAAAAEBAQEBAQEBAQEBAQAAAAAAAAAAAAAAAAAAAQEBAQEBAQEBAQEBAQEBAQEBAAAAAAAAAAAAAAAAAAABAQEBAQEBAQEBAQEBAQEBAQEAAAAAAAAAAAAAAAAAAAEBAQEBAQEBAQEBAQEBAQEBAQAAAAAAAAAAAAAAAAAAAQEBAQEBAQEBAQEBAAAAAAAAAAAAAAAAAAAAAAAAAAABAQEBAQEBAQEBAQEAAAAAAAAAAAAAAAAAAAAAAAAAAAEBAQEBAQEBAQEBAQAAAAAAAAAAAAAAAAAAAQEBAQEBAQEBAQEBAQEBAQEBAAAAAAAAAAAAAAAAAAABAQEBAQEBAQEBAQEBAQEBAQEAAAAAAAAAAAAAAAAAAAEBAQEBAQEBAQEBAQEBAQEBAQAAAAAAAAAAAAAAAAAAAQEBAQEBAQEBAQEBAQEBAQEBAAAAAAAAAAAAAAAAAAABAQEBAQEBAQEBAQEBAQEBAQEAAAAAAAAAAAAAAAAAAAEBAQEBAQEBAQEBAQ==" + }, + "palette" : { + "originalArgb8888" : [ -265674 ], + "convertedRgb565" : [ -122 ] } }, "diagnostics" : [ ] @@ -1032,14 +1032,14 @@ "last_modified" : 1774359772481, "fingerprint" : "eeb7cc665386299403b7be1c272375d5077f3647c587f8033aa8c9275f840562", "metadata" : { - "palette" : { - "originalArgb8888" : [ -265674 ], - "convertedRgb565" : [ -122 ] - }, "tile" : { "width" : 32, "height" : 32, "paletteIndices" : "AQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAAAAAAAAAAABAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEAAAAAAAAAAAEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQAAAAAAAAAAAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAAAAAAAAAAABAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEAAAAAAAAAAAEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQAAAAAAAAAAAQEBAQEBAQEBAQEBAAAAAAAAAAAAAAAAAAAAAAAAAAABAQEBAQEBAQEBAQEAAAAAAAAAAAAAAAAAAAAAAAAAAAEBAQEBAQEBAQEBAQAAAAAAAAAAAAAAAAAAAAAAAAAAAQEBAQEBAQEBAQEBAAAAAAAAAAAAAAAAAAAAAAAAAAABAQEBAQEBAQEBAQEAAAAAAAAAAAAAAAAAAAAAAAAAAAEBAQEBAQEBAQEBAQAAAAAAAAAAAAAAAAAAAAAAAAAAAQEBAQEBAQEBAQEBAAAAAAAAAAAAAAAAAAAAAAAAAAABAQEBAQEBAQEBAQEAAAAAAAAAAAAAAAAAAAAAAAAAAAEBAQEBAQEBAQEBAQAAAAAAAAAAAAAAAAAAAQEBAQEBAQEBAQEBAQEBAQEBAAAAAAAAAAAAAAAAAAABAQEBAQEBAQEBAQEBAQEBAQEAAAAAAAAAAAAAAAAAAAEBAQEBAQEBAQEBAQEBAQEBAQAAAAAAAAAAAAAAAAAAAQEBAQEBAQEBAQEBAAAAAAAAAAAAAAAAAAAAAAAAAAABAQEBAQEBAQEBAQEAAAAAAAAAAAAAAAAAAAAAAAAAAAEBAQEBAQEBAQEBAQAAAAAAAAAAAAAAAAAAAQEBAQEBAQEBAQEBAQEBAQEBAAAAAAAAAAAAAAAAAAABAQEBAQEBAQEBAQEBAQEBAQEAAAAAAAAAAAAAAAAAAAEBAQEBAQEBAQEBAQEBAQEBAQAAAAAAAAAAAAAAAAAAAQEBAQEBAQEBAQEBAQEBAQEBAAAAAAAAAAAAAAAAAAABAQEBAQEBAQEBAQEBAQEBAQEAAAAAAAAAAAAAAAAAAAEBAQEBAQEBAQEBAQ==" + }, + "palette" : { + "originalArgb8888" : [ -265674 ], + "convertedRgb565" : [ -122 ] } }, "diagnostics" : [ ] @@ -1050,14 +1050,14 @@ "last_modified" : 1774359772482, "fingerprint" : "eeb7cc665386299403b7be1c272375d5077f3647c587f8033aa8c9275f840562", "metadata" : { - "palette" : { - "originalArgb8888" : [ -265674 ], - "convertedRgb565" : [ -122 ] - }, "tile" : { "width" : 32, "height" : 32, "paletteIndices" : "AQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAAAAAAAAAAABAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEAAAAAAAAAAAEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQAAAAAAAAAAAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAAAAAAAAAAABAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEAAAAAAAAAAAEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQAAAAAAAAAAAQEBAQEBAQEBAQEBAAAAAAAAAAAAAAAAAAAAAAAAAAABAQEBAQEBAQEBAQEAAAAAAAAAAAAAAAAAAAAAAAAAAAEBAQEBAQEBAQEBAQAAAAAAAAAAAAAAAAAAAAAAAAAAAQEBAQEBAQEBAQEBAAAAAAAAAAAAAAAAAAAAAAAAAAABAQEBAQEBAQEBAQEAAAAAAAAAAAAAAAAAAAAAAAAAAAEBAQEBAQEBAQEBAQAAAAAAAAAAAAAAAAAAAAAAAAAAAQEBAQEBAQEBAQEBAAAAAAAAAAAAAAAAAAAAAAAAAAABAQEBAQEBAQEBAQEAAAAAAAAAAAAAAAAAAAAAAAAAAAEBAQEBAQEBAQEBAQAAAAAAAAAAAAAAAAAAAQEBAQEBAQEBAQEBAQEBAQEBAAAAAAAAAAAAAAAAAAABAQEBAQEBAQEBAQEBAQEBAQEAAAAAAAAAAAAAAAAAAAEBAQEBAQEBAQEBAQEBAQEBAQAAAAAAAAAAAAAAAAAAAQEBAQEBAQEBAQEBAAAAAAAAAAAAAAAAAAAAAAAAAAABAQEBAQEBAQEBAQEAAAAAAAAAAAAAAAAAAAAAAAAAAAEBAQEBAQEBAQEBAQAAAAAAAAAAAAAAAAAAAQEBAQEBAQEBAQEBAQEBAQEBAAAAAAAAAAAAAAAAAAABAQEBAQEBAQEBAQEBAQEBAQEAAAAAAAAAAAAAAAAAAAEBAQEBAQEBAQEBAQEBAQEBAQAAAAAAAAAAAAAAAAAAAQEBAQEBAQEBAQEBAQEBAQEBAAAAAAAAAAAAAAAAAAABAQEBAQEBAQEBAQEBAQEBAQEAAAAAAAAAAAAAAAAAAAEBAQEBAQEBAQEBAQ==" + }, + "palette" : { + "originalArgb8888" : [ -265674 ], + "convertedRgb565" : [ -122 ] } }, "diagnostics" : [ ] @@ -1068,14 +1068,14 @@ "last_modified" : 1774359772483, "fingerprint" : "eeb7cc665386299403b7be1c272375d5077f3647c587f8033aa8c9275f840562", "metadata" : { - "palette" : { - "originalArgb8888" : [ -265674 ], - "convertedRgb565" : [ -122 ] - }, "tile" : { "width" : 32, "height" : 32, "paletteIndices" : "AQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAAAAAAAAAAABAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEAAAAAAAAAAAEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQAAAAAAAAAAAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAAAAAAAAAAABAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEAAAAAAAAAAAEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQAAAAAAAAAAAQEBAQEBAQEBAQEBAAAAAAAAAAAAAAAAAAAAAAAAAAABAQEBAQEBAQEBAQEAAAAAAAAAAAAAAAAAAAAAAAAAAAEBAQEBAQEBAQEBAQAAAAAAAAAAAAAAAAAAAAAAAAAAAQEBAQEBAQEBAQEBAAAAAAAAAAAAAAAAAAAAAAAAAAABAQEBAQEBAQEBAQEAAAAAAAAAAAAAAAAAAAAAAAAAAAEBAQEBAQEBAQEBAQAAAAAAAAAAAAAAAAAAAAAAAAAAAQEBAQEBAQEBAQEBAAAAAAAAAAAAAAAAAAAAAAAAAAABAQEBAQEBAQEBAQEAAAAAAAAAAAAAAAAAAAAAAAAAAAEBAQEBAQEBAQEBAQAAAAAAAAAAAAAAAAAAAQEBAQEBAQEBAQEBAQEBAQEBAAAAAAAAAAAAAAAAAAABAQEBAQEBAQEBAQEBAQEBAQEAAAAAAAAAAAAAAAAAAAEBAQEBAQEBAQEBAQEBAQEBAQAAAAAAAAAAAAAAAAAAAQEBAQEBAQEBAQEBAAAAAAAAAAAAAAAAAAAAAAAAAAABAQEBAQEBAQEBAQEAAAAAAAAAAAAAAAAAAAAAAAAAAAEBAQEBAQEBAQEBAQAAAAAAAAAAAAAAAAAAAQEBAQEBAQEBAQEBAQEBAQEBAAAAAAAAAAAAAAAAAAABAQEBAQEBAQEBAQEBAQEBAQEAAAAAAAAAAAAAAAAAAAEBAQEBAQEBAQEBAQEBAQEBAQAAAAAAAAAAAAAAAAAAAQEBAQEBAQEBAQEBAQEBAQEBAAAAAAAAAAAAAAAAAAABAQEBAQEBAQEBAQEBAQEBAQEAAAAAAAAAAAAAAAAAAAEBAQEBAQEBAQEBAQ==" + }, + "palette" : { + "originalArgb8888" : [ -265674 ], + "convertedRgb565" : [ -122 ] } }, "diagnostics" : [ ] @@ -1086,14 +1086,14 @@ "last_modified" : 1774359772484, "fingerprint" : "eeb7cc665386299403b7be1c272375d5077f3647c587f8033aa8c9275f840562", "metadata" : { - "palette" : { - "originalArgb8888" : [ -265674 ], - "convertedRgb565" : [ -122 ] - }, "tile" : { "width" : 32, "height" : 32, "paletteIndices" : "AQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAAAAAAAAAAABAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEAAAAAAAAAAAEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQAAAAAAAAAAAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAAAAAAAAAAABAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEAAAAAAAAAAAEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQAAAAAAAAAAAQEBAQEBAQEBAQEBAAAAAAAAAAAAAAAAAAAAAAAAAAABAQEBAQEBAQEBAQEAAAAAAAAAAAAAAAAAAAAAAAAAAAEBAQEBAQEBAQEBAQAAAAAAAAAAAAAAAAAAAAAAAAAAAQEBAQEBAQEBAQEBAAAAAAAAAAAAAAAAAAAAAAAAAAABAQEBAQEBAQEBAQEAAAAAAAAAAAAAAAAAAAAAAAAAAAEBAQEBAQEBAQEBAQAAAAAAAAAAAAAAAAAAAAAAAAAAAQEBAQEBAQEBAQEBAAAAAAAAAAAAAAAAAAAAAAAAAAABAQEBAQEBAQEBAQEAAAAAAAAAAAAAAAAAAAAAAAAAAAEBAQEBAQEBAQEBAQAAAAAAAAAAAAAAAAAAAQEBAQEBAQEBAQEBAQEBAQEBAAAAAAAAAAAAAAAAAAABAQEBAQEBAQEBAQEBAQEBAQEAAAAAAAAAAAAAAAAAAAEBAQEBAQEBAQEBAQEBAQEBAQAAAAAAAAAAAAAAAAAAAQEBAQEBAQEBAQEBAAAAAAAAAAAAAAAAAAAAAAAAAAABAQEBAQEBAQEBAQEAAAAAAAAAAAAAAAAAAAAAAAAAAAEBAQEBAQEBAQEBAQAAAAAAAAAAAAAAAAAAAQEBAQEBAQEBAQEBAQEBAQEBAAAAAAAAAAAAAAAAAAABAQEBAQEBAQEBAQEBAQEBAQEAAAAAAAAAAAAAAAAAAAEBAQEBAQEBAQEBAQEBAQEBAQAAAAAAAAAAAAAAAAAAAQEBAQEBAQEBAQEBAQEBAQEBAAAAAAAAAAAAAAAAAAABAQEBAQEBAQEBAQEBAQEBAQEAAAAAAAAAAAAAAAAAAAEBAQEBAQEBAQEBAQ==" + }, + "palette" : { + "originalArgb8888" : [ -265674 ], + "convertedRgb565" : [ -122 ] } }, "diagnostics" : [ ] @@ -1104,14 +1104,14 @@ "last_modified" : 1774359772485, "fingerprint" : "eeb7cc665386299403b7be1c272375d5077f3647c587f8033aa8c9275f840562", "metadata" : { - "palette" : { - "originalArgb8888" : [ -265674 ], - "convertedRgb565" : [ -122 ] - }, "tile" : { "width" : 32, "height" : 32, "paletteIndices" : "AQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAAAAAAAAAAABAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEAAAAAAAAAAAEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQAAAAAAAAAAAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAAAAAAAAAAABAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEAAAAAAAAAAAEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQAAAAAAAAAAAQEBAQEBAQEBAQEBAAAAAAAAAAAAAAAAAAAAAAAAAAABAQEBAQEBAQEBAQEAAAAAAAAAAAAAAAAAAAAAAAAAAAEBAQEBAQEBAQEBAQAAAAAAAAAAAAAAAAAAAAAAAAAAAQEBAQEBAQEBAQEBAAAAAAAAAAAAAAAAAAAAAAAAAAABAQEBAQEBAQEBAQEAAAAAAAAAAAAAAAAAAAAAAAAAAAEBAQEBAQEBAQEBAQAAAAAAAAAAAAAAAAAAAAAAAAAAAQEBAQEBAQEBAQEBAAAAAAAAAAAAAAAAAAAAAAAAAAABAQEBAQEBAQEBAQEAAAAAAAAAAAAAAAAAAAAAAAAAAAEBAQEBAQEBAQEBAQAAAAAAAAAAAAAAAAAAAQEBAQEBAQEBAQEBAQEBAQEBAAAAAAAAAAAAAAAAAAABAQEBAQEBAQEBAQEBAQEBAQEAAAAAAAAAAAAAAAAAAAEBAQEBAQEBAQEBAQEBAQEBAQAAAAAAAAAAAAAAAAAAAQEBAQEBAQEBAQEBAAAAAAAAAAAAAAAAAAAAAAAAAAABAQEBAQEBAQEBAQEAAAAAAAAAAAAAAAAAAAAAAAAAAAEBAQEBAQEBAQEBAQAAAAAAAAAAAAAAAAAAAQEBAQEBAQEBAQEBAQEBAQEBAAAAAAAAAAAAAAAAAAABAQEBAQEBAQEBAQEBAQEBAQEAAAAAAAAAAAAAAAAAAAEBAQEBAQEBAQEBAQEBAQEBAQAAAAAAAAAAAAAAAAAAAQEBAQEBAQEBAQEBAQEBAQEBAAAAAAAAAAAAAAAAAAABAQEBAQEBAQEBAQEBAQEBAQEAAAAAAAAAAAAAAAAAAAEBAQEBAQEBAQEBAQ==" + }, + "palette" : { + "originalArgb8888" : [ -265674 ], + "convertedRgb565" : [ -122 ] } }, "diagnostics" : [ ] @@ -1122,14 +1122,14 @@ "last_modified" : 1774359772487, "fingerprint" : "eeb7cc665386299403b7be1c272375d5077f3647c587f8033aa8c9275f840562", "metadata" : { - "palette" : { - "originalArgb8888" : [ -265674 ], - "convertedRgb565" : [ -122 ] - }, "tile" : { "width" : 32, "height" : 32, "paletteIndices" : "AQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAAAAAAAAAAABAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEAAAAAAAAAAAEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQAAAAAAAAAAAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAAAAAAAAAAABAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEAAAAAAAAAAAEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQAAAAAAAAAAAQEBAQEBAQEBAQEBAAAAAAAAAAAAAAAAAAAAAAAAAAABAQEBAQEBAQEBAQEAAAAAAAAAAAAAAAAAAAAAAAAAAAEBAQEBAQEBAQEBAQAAAAAAAAAAAAAAAAAAAAAAAAAAAQEBAQEBAQEBAQEBAAAAAAAAAAAAAAAAAAAAAAAAAAABAQEBAQEBAQEBAQEAAAAAAAAAAAAAAAAAAAAAAAAAAAEBAQEBAQEBAQEBAQAAAAAAAAAAAAAAAAAAAAAAAAAAAQEBAQEBAQEBAQEBAAAAAAAAAAAAAAAAAAAAAAAAAAABAQEBAQEBAQEBAQEAAAAAAAAAAAAAAAAAAAAAAAAAAAEBAQEBAQEBAQEBAQAAAAAAAAAAAAAAAAAAAQEBAQEBAQEBAQEBAQEBAQEBAAAAAAAAAAAAAAAAAAABAQEBAQEBAQEBAQEBAQEBAQEAAAAAAAAAAAAAAAAAAAEBAQEBAQEBAQEBAQEBAQEBAQAAAAAAAAAAAAAAAAAAAQEBAQEBAQEBAQEBAAAAAAAAAAAAAAAAAAAAAAAAAAABAQEBAQEBAQEBAQEAAAAAAAAAAAAAAAAAAAAAAAAAAAEBAQEBAQEBAQEBAQAAAAAAAAAAAAAAAAAAAQEBAQEBAQEBAQEBAQEBAQEBAAAAAAAAAAAAAAAAAAABAQEBAQEBAQEBAQEBAQEBAQEAAAAAAAAAAAAAAAAAAAEBAQEBAQEBAQEBAQEBAQEBAQAAAAAAAAAAAAAAAAAAAQEBAQEBAQEBAQEBAQEBAQEBAAAAAAAAAAAAAAAAAAABAQEBAQEBAQEBAQEBAQEBAQEAAAAAAAAAAAAAAAAAAAEBAQEBAQEBAQEBAQ==" + }, + "palette" : { + "originalArgb8888" : [ -265674 ], + "convertedRgb565" : [ -122 ] } }, "diagnostics" : [ ] @@ -1140,14 +1140,14 @@ "last_modified" : 1774359772488, "fingerprint" : "eeb7cc665386299403b7be1c272375d5077f3647c587f8033aa8c9275f840562", "metadata" : { - "palette" : { - "originalArgb8888" : [ -265674 ], - "convertedRgb565" : [ -122 ] - }, "tile" : { "width" : 32, "height" : 32, "paletteIndices" : "AQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAAAAAAAAAAABAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEAAAAAAAAAAAEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQAAAAAAAAAAAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAAAAAAAAAAABAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEAAAAAAAAAAAEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQAAAAAAAAAAAQEBAQEBAQEBAQEBAAAAAAAAAAAAAAAAAAAAAAAAAAABAQEBAQEBAQEBAQEAAAAAAAAAAAAAAAAAAAAAAAAAAAEBAQEBAQEBAQEBAQAAAAAAAAAAAAAAAAAAAAAAAAAAAQEBAQEBAQEBAQEBAAAAAAAAAAAAAAAAAAAAAAAAAAABAQEBAQEBAQEBAQEAAAAAAAAAAAAAAAAAAAAAAAAAAAEBAQEBAQEBAQEBAQAAAAAAAAAAAAAAAAAAAAAAAAAAAQEBAQEBAQEBAQEBAAAAAAAAAAAAAAAAAAAAAAAAAAABAQEBAQEBAQEBAQEAAAAAAAAAAAAAAAAAAAAAAAAAAAEBAQEBAQEBAQEBAQAAAAAAAAAAAAAAAAAAAQEBAQEBAQEBAQEBAQEBAQEBAAAAAAAAAAAAAAAAAAABAQEBAQEBAQEBAQEBAQEBAQEAAAAAAAAAAAAAAAAAAAEBAQEBAQEBAQEBAQEBAQEBAQAAAAAAAAAAAAAAAAAAAQEBAQEBAQEBAQEBAAAAAAAAAAAAAAAAAAAAAAAAAAABAQEBAQEBAQEBAQEAAAAAAAAAAAAAAAAAAAAAAAAAAAEBAQEBAQEBAQEBAQAAAAAAAAAAAAAAAAAAAQEBAQEBAQEBAQEBAQEBAQEBAAAAAAAAAAAAAAAAAAABAQEBAQEBAQEBAQEBAQEBAQEAAAAAAAAAAAAAAAAAAAEBAQEBAQEBAQEBAQEBAQEBAQAAAAAAAAAAAAAAAAAAAQEBAQEBAQEBAQEBAQEBAQEBAAAAAAAAAAAAAAAAAAABAQEBAQEBAQEBAQEBAQEBAQEAAAAAAAAAAAAAAAAAAAEBAQEBAQEBAQEBAQ==" + }, + "palette" : { + "originalArgb8888" : [ -265674 ], + "convertedRgb565" : [ -122 ] } }, "diagnostics" : [ ] @@ -1158,14 +1158,14 @@ "last_modified" : 1774359772489, "fingerprint" : "eeb7cc665386299403b7be1c272375d5077f3647c587f8033aa8c9275f840562", "metadata" : { - "palette" : { - "originalArgb8888" : [ -265674 ], - "convertedRgb565" : [ -122 ] - }, "tile" : { "width" : 32, "height" : 32, "paletteIndices" : "AQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAAAAAAAAAAABAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEAAAAAAAAAAAEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQAAAAAAAAAAAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAAAAAAAAAAABAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEAAAAAAAAAAAEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQAAAAAAAAAAAQEBAQEBAQEBAQEBAAAAAAAAAAAAAAAAAAAAAAAAAAABAQEBAQEBAQEBAQEAAAAAAAAAAAAAAAAAAAAAAAAAAAEBAQEBAQEBAQEBAQAAAAAAAAAAAAAAAAAAAAAAAAAAAQEBAQEBAQEBAQEBAAAAAAAAAAAAAAAAAAAAAAAAAAABAQEBAQEBAQEBAQEAAAAAAAAAAAAAAAAAAAAAAAAAAAEBAQEBAQEBAQEBAQAAAAAAAAAAAAAAAAAAAAAAAAAAAQEBAQEBAQEBAQEBAAAAAAAAAAAAAAAAAAAAAAAAAAABAQEBAQEBAQEBAQEAAAAAAAAAAAAAAAAAAAAAAAAAAAEBAQEBAQEBAQEBAQAAAAAAAAAAAAAAAAAAAQEBAQEBAQEBAQEBAQEBAQEBAAAAAAAAAAAAAAAAAAABAQEBAQEBAQEBAQEBAQEBAQEAAAAAAAAAAAAAAAAAAAEBAQEBAQEBAQEBAQEBAQEBAQAAAAAAAAAAAAAAAAAAAQEBAQEBAQEBAQEBAAAAAAAAAAAAAAAAAAAAAAAAAAABAQEBAQEBAQEBAQEAAAAAAAAAAAAAAAAAAAAAAAAAAAEBAQEBAQEBAQEBAQAAAAAAAAAAAAAAAAAAAQEBAQEBAQEBAQEBAQEBAQEBAAAAAAAAAAAAAAAAAAABAQEBAQEBAQEBAQEBAQEBAQEAAAAAAAAAAAAAAAAAAAEBAQEBAQEBAQEBAQEBAQEBAQAAAAAAAAAAAAAAAAAAAQEBAQEBAQEBAQEBAQEBAQEBAAAAAAAAAAAAAAAAAAABAQEBAQEBAQEBAQEBAQEBAQEAAAAAAAAAAAAAAAAAAAEBAQEBAQEBAQEBAQ==" + }, + "palette" : { + "originalArgb8888" : [ -265674 ], + "convertedRgb565" : [ -122 ] } }, "diagnostics" : [ ] @@ -1176,14 +1176,14 @@ "last_modified" : 1774359772491, "fingerprint" : "eeb7cc665386299403b7be1c272375d5077f3647c587f8033aa8c9275f840562", "metadata" : { - "palette" : { - "originalArgb8888" : [ -265674 ], - "convertedRgb565" : [ -122 ] - }, "tile" : { "width" : 32, "height" : 32, "paletteIndices" : "AQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAAAAAAAAAAABAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEAAAAAAAAAAAEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQAAAAAAAAAAAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAAAAAAAAAAABAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEAAAAAAAAAAAEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQAAAAAAAAAAAQEBAQEBAQEBAQEBAAAAAAAAAAAAAAAAAAAAAAAAAAABAQEBAQEBAQEBAQEAAAAAAAAAAAAAAAAAAAAAAAAAAAEBAQEBAQEBAQEBAQAAAAAAAAAAAAAAAAAAAAAAAAAAAQEBAQEBAQEBAQEBAAAAAAAAAAAAAAAAAAAAAAAAAAABAQEBAQEBAQEBAQEAAAAAAAAAAAAAAAAAAAAAAAAAAAEBAQEBAQEBAQEBAQAAAAAAAAAAAAAAAAAAAAAAAAAAAQEBAQEBAQEBAQEBAAAAAAAAAAAAAAAAAAAAAAAAAAABAQEBAQEBAQEBAQEAAAAAAAAAAAAAAAAAAAAAAAAAAAEBAQEBAQEBAQEBAQAAAAAAAAAAAAAAAAAAAQEBAQEBAQEBAQEBAQEBAQEBAAAAAAAAAAAAAAAAAAABAQEBAQEBAQEBAQEBAQEBAQEAAAAAAAAAAAAAAAAAAAEBAQEBAQEBAQEBAQEBAQEBAQAAAAAAAAAAAAAAAAAAAQEBAQEBAQEBAQEBAAAAAAAAAAAAAAAAAAAAAAAAAAABAQEBAQEBAQEBAQEAAAAAAAAAAAAAAAAAAAAAAAAAAAEBAQEBAQEBAQEBAQAAAAAAAAAAAAAAAAAAAQEBAQEBAQEBAQEBAQEBAQEBAAAAAAAAAAAAAAAAAAABAQEBAQEBAQEBAQEBAQEBAQEAAAAAAAAAAAAAAAAAAAEBAQEBAQEBAQEBAQEBAQEBAQAAAAAAAAAAAAAAAAAAAQEBAQEBAQEBAQEBAQEBAQEBAAAAAAAAAAAAAAAAAAABAQEBAQEBAQEBAQEBAQEBAQEAAAAAAAAAAAAAAAAAAAEBAQEBAQEBAQEBAQ==" + }, + "palette" : { + "originalArgb8888" : [ -265674 ], + "convertedRgb565" : [ -122 ] } }, "diagnostics" : [ ] @@ -1194,14 +1194,14 @@ "last_modified" : 1774359772492, "fingerprint" : "eeb7cc665386299403b7be1c272375d5077f3647c587f8033aa8c9275f840562", "metadata" : { - "palette" : { - "originalArgb8888" : [ -265674 ], - "convertedRgb565" : [ -122 ] - }, "tile" : { "width" : 32, "height" : 32, "paletteIndices" : "AQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAAAAAAAAAAABAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEAAAAAAAAAAAEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQAAAAAAAAAAAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAAAAAAAAAAABAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEAAAAAAAAAAAEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQAAAAAAAAAAAQEBAQEBAQEBAQEBAAAAAAAAAAAAAAAAAAAAAAAAAAABAQEBAQEBAQEBAQEAAAAAAAAAAAAAAAAAAAAAAAAAAAEBAQEBAQEBAQEBAQAAAAAAAAAAAAAAAAAAAAAAAAAAAQEBAQEBAQEBAQEBAAAAAAAAAAAAAAAAAAAAAAAAAAABAQEBAQEBAQEBAQEAAAAAAAAAAAAAAAAAAAAAAAAAAAEBAQEBAQEBAQEBAQAAAAAAAAAAAAAAAAAAAAAAAAAAAQEBAQEBAQEBAQEBAAAAAAAAAAAAAAAAAAAAAAAAAAABAQEBAQEBAQEBAQEAAAAAAAAAAAAAAAAAAAAAAAAAAAEBAQEBAQEBAQEBAQAAAAAAAAAAAAAAAAAAAQEBAQEBAQEBAQEBAQEBAQEBAAAAAAAAAAAAAAAAAAABAQEBAQEBAQEBAQEBAQEBAQEAAAAAAAAAAAAAAAAAAAEBAQEBAQEBAQEBAQEBAQEBAQAAAAAAAAAAAAAAAAAAAQEBAQEBAQEBAQEBAAAAAAAAAAAAAAAAAAAAAAAAAAABAQEBAQEBAQEBAQEAAAAAAAAAAAAAAAAAAAAAAAAAAAEBAQEBAQEBAQEBAQAAAAAAAAAAAAAAAAAAAQEBAQEBAQEBAQEBAQEBAQEBAAAAAAAAAAAAAAAAAAABAQEBAQEBAQEBAQEBAQEBAQEAAAAAAAAAAAAAAAAAAAEBAQEBAQEBAQEBAQEBAQEBAQAAAAAAAAAAAAAAAAAAAQEBAQEBAQEBAQEBAQEBAQEBAAAAAAAAAAAAAAAAAAABAQEBAQEBAQEBAQEBAQEBAQEAAAAAAAAAAAAAAAAAAAEBAQEBAQEBAQEBAQ==" + }, + "palette" : { + "originalArgb8888" : [ -265674 ], + "convertedRgb565" : [ -122 ] } }, "diagnostics" : [ ] @@ -1212,14 +1212,14 @@ "last_modified" : 1774359772493, "fingerprint" : "eeb7cc665386299403b7be1c272375d5077f3647c587f8033aa8c9275f840562", "metadata" : { - "palette" : { - "originalArgb8888" : [ -265674 ], - "convertedRgb565" : [ -122 ] - }, "tile" : { "width" : 32, "height" : 32, "paletteIndices" : "AQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAAAAAAAAAAABAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEAAAAAAAAAAAEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQAAAAAAAAAAAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAAAAAAAAAAABAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEAAAAAAAAAAAEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQAAAAAAAAAAAQEBAQEBAQEBAQEBAAAAAAAAAAAAAAAAAAAAAAAAAAABAQEBAQEBAQEBAQEAAAAAAAAAAAAAAAAAAAAAAAAAAAEBAQEBAQEBAQEBAQAAAAAAAAAAAAAAAAAAAAAAAAAAAQEBAQEBAQEBAQEBAAAAAAAAAAAAAAAAAAAAAAAAAAABAQEBAQEBAQEBAQEAAAAAAAAAAAAAAAAAAAAAAAAAAAEBAQEBAQEBAQEBAQAAAAAAAAAAAAAAAAAAAAAAAAAAAQEBAQEBAQEBAQEBAAAAAAAAAAAAAAAAAAAAAAAAAAABAQEBAQEBAQEBAQEAAAAAAAAAAAAAAAAAAAAAAAAAAAEBAQEBAQEBAQEBAQAAAAAAAAAAAAAAAAAAAQEBAQEBAQEBAQEBAQEBAQEBAAAAAAAAAAAAAAAAAAABAQEBAQEBAQEBAQEBAQEBAQEAAAAAAAAAAAAAAAAAAAEBAQEBAQEBAQEBAQEBAQEBAQAAAAAAAAAAAAAAAAAAAQEBAQEBAQEBAQEBAAAAAAAAAAAAAAAAAAAAAAAAAAABAQEBAQEBAQEBAQEAAAAAAAAAAAAAAAAAAAAAAAAAAAEBAQEBAQEBAQEBAQAAAAAAAAAAAAAAAAAAAQEBAQEBAQEBAQEBAQEBAQEBAAAAAAAAAAAAAAAAAAABAQEBAQEBAQEBAQEBAQEBAQEAAAAAAAAAAAAAAAAAAAEBAQEBAQEBAQEBAQEBAQEBAQAAAAAAAAAAAAAAAAAAAQEBAQEBAQEBAQEBAQEBAQEBAAAAAAAAAAAAAAAAAAABAQEBAQEBAQEBAQEBAQEBAQEAAAAAAAAAAAAAAAAAAAEBAQEBAQEBAQEBAQ==" + }, + "palette" : { + "originalArgb8888" : [ -265674 ], + "convertedRgb565" : [ -122 ] } }, "diagnostics" : [ ] @@ -1230,14 +1230,14 @@ "last_modified" : 1774359772494, "fingerprint" : "eeb7cc665386299403b7be1c272375d5077f3647c587f8033aa8c9275f840562", "metadata" : { - "palette" : { - "originalArgb8888" : [ -265674 ], - "convertedRgb565" : [ -122 ] - }, "tile" : { "width" : 32, "height" : 32, "paletteIndices" : "AQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAAAAAAAAAAABAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEAAAAAAAAAAAEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQAAAAAAAAAAAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAAAAAAAAAAABAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEAAAAAAAAAAAEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQAAAAAAAAAAAQEBAQEBAQEBAQEBAAAAAAAAAAAAAAAAAAAAAAAAAAABAQEBAQEBAQEBAQEAAAAAAAAAAAAAAAAAAAAAAAAAAAEBAQEBAQEBAQEBAQAAAAAAAAAAAAAAAAAAAAAAAAAAAQEBAQEBAQEBAQEBAAAAAAAAAAAAAAAAAAAAAAAAAAABAQEBAQEBAQEBAQEAAAAAAAAAAAAAAAAAAAAAAAAAAAEBAQEBAQEBAQEBAQAAAAAAAAAAAAAAAAAAAAAAAAAAAQEBAQEBAQEBAQEBAAAAAAAAAAAAAAAAAAAAAAAAAAABAQEBAQEBAQEBAQEAAAAAAAAAAAAAAAAAAAAAAAAAAAEBAQEBAQEBAQEBAQAAAAAAAAAAAAAAAAAAAQEBAQEBAQEBAQEBAQEBAQEBAAAAAAAAAAAAAAAAAAABAQEBAQEBAQEBAQEBAQEBAQEAAAAAAAAAAAAAAAAAAAEBAQEBAQEBAQEBAQEBAQEBAQAAAAAAAAAAAAAAAAAAAQEBAQEBAQEBAQEBAAAAAAAAAAAAAAAAAAAAAAAAAAABAQEBAQEBAQEBAQEAAAAAAAAAAAAAAAAAAAAAAAAAAAEBAQEBAQEBAQEBAQAAAAAAAAAAAAAAAAAAAQEBAQEBAQEBAQEBAQEBAQEBAAAAAAAAAAAAAAAAAAABAQEBAQEBAQEBAQEBAQEBAQEAAAAAAAAAAAAAAAAAAAEBAQEBAQEBAQEBAQEBAQEBAQAAAAAAAAAAAAAAAAAAAQEBAQEBAQEBAQEBAQEBAQEBAAAAAAAAAAAAAAAAAAABAQEBAQEBAQEBAQEBAQEBAQEAAAAAAAAAAAAAAAAAAAEBAQEBAQEBAQEBAQ==" + }, + "palette" : { + "originalArgb8888" : [ -265674 ], + "convertedRgb565" : [ -122 ] } }, "diagnostics" : [ ] @@ -1248,14 +1248,14 @@ "last_modified" : 1774359772495, "fingerprint" : "eeb7cc665386299403b7be1c272375d5077f3647c587f8033aa8c9275f840562", "metadata" : { - "palette" : { - "originalArgb8888" : [ -265674 ], - "convertedRgb565" : [ -122 ] - }, "tile" : { "width" : 32, "height" : 32, "paletteIndices" : "AQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAAAAAAAAAAABAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEAAAAAAAAAAAEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQAAAAAAAAAAAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAAAAAAAAAAABAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEAAAAAAAAAAAEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQAAAAAAAAAAAQEBAQEBAQEBAQEBAAAAAAAAAAAAAAAAAAAAAAAAAAABAQEBAQEBAQEBAQEAAAAAAAAAAAAAAAAAAAAAAAAAAAEBAQEBAQEBAQEBAQAAAAAAAAAAAAAAAAAAAAAAAAAAAQEBAQEBAQEBAQEBAAAAAAAAAAAAAAAAAAAAAAAAAAABAQEBAQEBAQEBAQEAAAAAAAAAAAAAAAAAAAAAAAAAAAEBAQEBAQEBAQEBAQAAAAAAAAAAAAAAAAAAAAAAAAAAAQEBAQEBAQEBAQEBAAAAAAAAAAAAAAAAAAAAAAAAAAABAQEBAQEBAQEBAQEAAAAAAAAAAAAAAAAAAAAAAAAAAAEBAQEBAQEBAQEBAQAAAAAAAAAAAAAAAAAAAQEBAQEBAQEBAQEBAQEBAQEBAAAAAAAAAAAAAAAAAAABAQEBAQEBAQEBAQEBAQEBAQEAAAAAAAAAAAAAAAAAAAEBAQEBAQEBAQEBAQEBAQEBAQAAAAAAAAAAAAAAAAAAAQEBAQEBAQEBAQEBAAAAAAAAAAAAAAAAAAAAAAAAAAABAQEBAQEBAQEBAQEAAAAAAAAAAAAAAAAAAAAAAAAAAAEBAQEBAQEBAQEBAQAAAAAAAAAAAAAAAAAAAQEBAQEBAQEBAQEBAQEBAQEBAAAAAAAAAAAAAAAAAAABAQEBAQEBAQEBAQEBAQEBAQEAAAAAAAAAAAAAAAAAAAEBAQEBAQEBAQEBAQEBAQEBAQAAAAAAAAAAAAAAAAAAAQEBAQEBAQEBAQEBAQEBAQEBAAAAAAAAAAAAAAAAAAABAQEBAQEBAQEBAQEBAQEBAQEAAAAAAAAAAAAAAAAAAAEBAQEBAQEBAQEBAQ==" + }, + "palette" : { + "originalArgb8888" : [ -265674 ], + "convertedRgb565" : [ -122 ] } }, "diagnostics" : [ ] @@ -1266,14 +1266,14 @@ "last_modified" : 1775797786950, "fingerprint" : "0526996900bdeef23c72fe987fb45800f11895946dcd5f0f7f8390c879069a37", "metadata" : { - "palette" : { - "originalArgb8888" : [ -265674, -1736296, -13905598, -11518505, -14439577, -2467509 ], - "convertedRgb565" : [ -122, -7149, 11912, 20986, 9548, -9527 ] - }, "tile" : { "width" : 32, "height" : 32, "paletteIndices" : "AQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQECAgIBAQEBAQEBAQEBAQEBAQEBAwMDAwMDAQEBAQEBAgICAgICAgIBAQEBAQEBAQEBAQMDAwMDAwMBAQEBAQICAgICAgICAQEBAQEBAQEBAQEBAQMDAwMDAQEBAQEBAgICAgICAgEBAQEBAQQEBAQBAQEBAQEBAQEBAQEBAQEBAgICAgIBAQEBAQEEBAQEBAQBAQEBAQEBAQEBAQEBAQEBAgECAQEBAQEBAQQEBAQEAQEBAQEBAAAAAAAAAAABAQECAQEBAQEBAQEEBAQEBAEBAQEBAQEAAAAAAAAAAAEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQAAAAAAAAAAAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAAAAAAAAAAABAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEAAAAAAAAAAAEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQAAAAAAAAAAAQEBAQEBAQEBAQEBAAAAAAAAAAAAAAAAAAAAAAAAAAABAQEBAQEBAQEBAQEAAAAAAAAAAAAAAAAAAAAAAAAAAAEBAQEBAQEBAQEBAQAAAAAAAAAAAAAAAAAAAAAAAAAAAQEBAQEBAQUBAQEBAAAAAAAAAAAAAAAAAAAAAAAAAAABAQEBAQUFBQEBAQEAAAAAAAAAAAAAAAAAAAAAAAAAAAEBAQEFBQUFBQEBAQAAAAAAAAAAAAAAAAAAAAAAAAAAAQEBBQUFBQUBAQEBAAAAAAAAAAAAAAAAAAAAAAAAAAABAQEBBQUFAQEBAQEAAAAAAAAAAAAAAAAAAAAAAAAAAAEBAQEBAQEBAQEBAQAAAAAAAAAAAAAAAAAAAQEBAQEBAQEBAQEBAQEBAQEBAAAAAAAAAAAAAAAAAAABAQEBAQEBAQEBAQEBAQEBAQEAAAAAAAAAAAAAAAAAAAEBAQEBAQYGBgYBAQEBAQEBAQAAAAAAAAAAAAAAAAAAAQEBAQEBBgYGBgEBAAAAAAAAAAAAAAAAAAAAAAAAAAABAQEBAQEGBgYGAQEAAAAAAAAAAAAAAAAAAAAAAAAAAAEBAQEBAQYGBgYBAQAAAAAAAAAAAAAAAAAAAQEBAQEBAQEBAQEBAQYGAQEBAAAAAAAAAAAAAAAAAAABAQEBAQEBAQEBAQEBAQEBAQEAAAAAAAAAAAAAAAAAAAEBAQEBAQEBAQEBAQEBAQEBAQAAAAAAAAAAAAAAAAAAAQEBAQEBAQEBAQEBAQEBAQEBAAAAAAAAAAAAAAAAAAABAQEBAQEBAQEBAQEBAQEBAQEAAAAAAAAAAAAAAAAAAAEBAQEBAQEBAQEBAQ==" + }, + "palette" : { + "originalArgb8888" : [ -265674, -1736296, -13905598, -11518505, -14439577, -2467509 ], + "convertedRgb565" : [ -122, -7149, 11912, 20986, 9548, -9527 ] } }, "diagnostics" : [ ] @@ -1314,14 +1314,14 @@ "last_modified" : 1775797786770, "fingerprint" : "aa7d241deabcebe29a6096e14eaf16fdc06cf06380c11a507620b00fc7bff094", "metadata" : { - "palette" : { - "originalArgb8888" : [ -265674 ], - "convertedRgb565" : [ -122 ] - }, "tile" : { "width" : 16, "height" : 16, "paletteIndices" : "AQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAAAAAAEBAQEBAQEBAQEBAQAAAAABAQEBAQEBAQEBAQEAAAAAAQEBAQEBAAAAAAAAAAAAAAEBAQEBAQAAAAAAAAAAAAABAQEBAQEAAAAAAAAAAAAAAQEBAQEBAAAAAAAAAAAAAAEBAQEBAQAAAAAAAAABAQEBAQEBAQEAAAAAAAAAAQEBAQEBAAAAAAAAAAAAAAEBAQEBAQAAAAAAAAABAQEBAQEBAQEAAAAAAAAAAQEBAQEBAQEBAAAAAAAAAAEBAQEBAQ==" + }, + "palette" : { + "originalArgb8888" : [ -265674 ], + "convertedRgb565" : [ -122 ] } }, "diagnostics" : [ ] @@ -1344,14 +1344,14 @@ "last_modified" : 1775797786709, "fingerprint" : "6ca635a7906067b6a2a8460a8562718c445783e6df18b9f2c80c83c5ac569db6", "metadata" : { - "palette" : { - "originalArgb8888" : [ -130562, -14145496, -2043712, -460560, -13082456, -6252424, -10977088 ], - "convertedRgb565" : [ -2017, 10565, -6504, -34, 15125, -23345, 23576 ] - }, "tile" : { "width" : 32, "height" : 32, "paletteIndices" : "AQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQICAgICAgICAgAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAICAwMDAwMDAgAAAAAAAAAAAAACAgIAAAAAAAAAAAAAAAIEBQUFBQUDAgAAAAAAAgICAgMDAwIAAAAAAAAAAAAAAgQFAwYGBgUDAgICAgIDAwMDBQUFAwIAAAAAAAAAAAACBAUDBgYGBgUEBAQEAwUFBQUGAwMFBAICAAAAAAAAAAIEBQMGBgYGAwUFBwcFBgYGBgMDAwMFBAQCAgAAAAAAAgQFAwYGBgMDAwQEBAMGBgYGBgMDAwMHBwQDAgAAAAACBAUDBgYGAwMDAwQEAwYGBgYGAwMDBAQEBQUDAgIAAAIEBQMGBgYDAwMDBAQDBgYGBgYDAwMDBAQDAwUGAgAAAgQFAwYGBgMDAwMEBAMGBgYGBQUFBQUEBAUFBgIAAAACBAUDBgYGAwMDAwQEAwYGBQUGAwMDAwcHAwYCAAAAAAIEBQMFBQUFBQMDBAQDBgUGBgICAgICBAQCAgAAAAAAAgQFBQYGBgYDBQMEBAMFBgICAAAAAAACAgAAAAAAAAACBAMDBgICAgIDBQcHBQYCAAAAAAAAAAAAAAAAAAAAAgIDAwMCAAAAAAIEBAMDAgAAAAAAAAAAAAAAAAAAAAICAgICAgAAAAAAAAICAgIAAAAAAAAAAAAAAAAAAAAAAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQ==" + }, + "palette" : { + "originalArgb8888" : [ -130562, -14145496, -2043712, -460560, -13082456, -6252424, -10977088 ], + "convertedRgb565" : [ -2017, 10565, -6504, -34, 15125, -23345, 23576 ] } }, "diagnostics" : [ { @@ -1396,14 +1396,14 @@ "last_modified" : 1775797786706, "fingerprint" : "7feab8c868bb446afd3dd7250e70504fb0ca228f463650d2dd7c525144e0b321", "metadata" : { - "palette" : { - "originalArgb8888" : [ -16777216, -2109505, -526353, -395279, -130562, -13082456, -10911807, -6318217, -6186631, -6187143, -6318215, -13148249, -13016663, -14080215 ], - "convertedRgb565" : [ 0, -8585, -2115, -66, -2017, 15125, 23544, -25426, -23345, -23377, -25425, 13044, 15125, 10533 ] - }, "tile" : { "width" : 32, "height" : 32, "paletteIndices" : "AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAEBAQEBAQEAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAEBAgMDBAEBAQEBBQUFAAUFBQUFBQUBAQAAAAAAAAAAAAECBgcHBAIICAkBBQUFBQUFBQEBAQICAQEAAAAFBQAAAQIGAwMHBgYGBgIBBQUFBQEBCgIIBgYDBAEBBQUFAAABAgYDAwIJCQsJBgIBAQEBCAgMDA0JAgcHAwMBBQUAAAECBgMDAgsLCwsLBgMDAwIGBgkCCwILAgIHAwEFBQAAAQIGAwMCCQkJCQkCBgcHBgsLCwsCCwICAwMHAwEFAAABAgYDAgkJCQkJCQICAwMCCQkJAgkGBgYHBwcDDgUAAAECBwMCCQkJCQkJAgIDAgkJCQkGBgsCAwMDAwQEAQAAAQIHAwIJCQkJCQkCAgMCCQkJBgkLAQEBAQEBAQQBAAABAgcDAgkJCQkJAgICAwILCQYJAQEFBQUFBQUFAQEAAAECBwMCCQkJCQYGAgIDAgkGCwEFBQUFBQUFBQAAAAAAAQIHAwIJCQYGCQIGBgcMBgkBBQUFBQUFBQAAAAAAAAABAgcGBgYGCQsBAQIDBAIKAQUFBQUFBQAAAAAAAAAAAQECAwIJCQkBAQAAAQEBAQEAAAAAAAAAAAAAAAAAAAEBAQEBAQEBAQAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA==" + }, + "palette" : { + "originalArgb8888" : [ -16777216, -2109505, -526353, -395279, -130562, -13082456, -10911807, -6318217, -6186631, -6187143, -6318215, -13148249, -13016663, -14080215 ], + "convertedRgb565" : [ 0, -8585, -2115, -66, -2017, 15125, 23544, -25426, -23345, -23377, -25425, 13044, 15125, 10533 ] } }, "diagnostics" : [ ] @@ -1414,14 +1414,14 @@ "last_modified" : 1775797786710, "fingerprint" : "c363f3ef7f32d9b249c7dc8babdb3eb5aae68c524099e5e97290202b054dda71", "metadata" : { - "palette" : { - "originalArgb8888" : [ -14671840, -11431408, -9326048, -802016, -3964416, -5086944, -789517, -810399, -1863087, -10403552, -5078447 ], - "convertedRgb565" : [ 8452, 21634, 30084, -2556, -15360, -19708, -2146, -2804, -7030, 25092, -19446 ] - }, "tile" : { "width" : 32, "height" : 32, "paletteIndices" : "AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAABAQEBAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAEBAQICAwMBAQAAAAAAAAAAAAAAAAAAAAAAAAAAAAABBAQBAgIDAwMCAQAAAAAAAAAAAAAAAAAAAAAAAAAAAQUFBAQBAgIDAgICAQAAAAAAAAAAAAAAAAAAAAAAAAABBQEFBAUBAgICAgMBAAAAAAAAAAAAAAAAAAAAAAAAAAABBgEFBQUBAgECAgMBAAAAAAAAAAAAAAAAAAAAAAAAAAEGBwEFBAEBCAECAwEAAAAAAAAAAAAAAAAAAAAAAAAAAQgBBwEEAQgJAQICAQAAAAAAAAAAAAAAAAAAAAAAAAEICAEHAQQBCQYBAgIBAAAAAAAAAAAAAAAAAAAAAAAAAAEGCQkBBQEGAQUBAgEAAAAAAAAAAAAAAAAAAAAAAAAAAAEBBgYBBgEBAQABAAAAAAAAAAAAAAAAAAAAAAAAAAAAAQcBAQEBAgIBAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAECAwECAwIBAgEAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAQECAQcHBwECAQAAAAAAAAAAAAAAAAAAAAAAAAAAAAABBAEBAQEBAQECAQAAAAAAAAAAAAAAAAAAAAAAAAAAAAABAgEJCgoBAgEAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAQEBAQEJCQEBAQAAAAAAAAAAAAAAAAAAAAAAAAAAAAEBAQEKAQEBAQEBAQAAAAAAAAAAAAAAAAAAAAAAAAAAAQEBAQELCwoKAQEBAAAAAAAAAAAAAAAAAAAAAAAAAAAAAQEBAQEBAQEBAQAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAEBAQEBAQAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA==" + }, + "palette" : { + "originalArgb8888" : [ -14671840, -11431408, -9326048, -802016, -3964416, -5086944, -789517, -810399, -1863087, -10403552, -5078447 ], + "convertedRgb565" : [ 8452, 21634, 30084, -2556, -15360, -19708, -2146, -2804, -7030, 25092, -19446 ] } }, "diagnostics" : [ ] @@ -1432,14 +1432,14 @@ "last_modified" : 1775797786711, "fingerprint" : "e2130efbb9643b41a4fb62619f2713402f9622c7db040fe18d929609ef70b89a", "metadata" : { - "palette" : { - "originalArgb8888" : [ -14671840, -11431408, -9326048, -802016, -3964416, -5086944, -789517, -810399, -1863087, -10403552, -5078447 ], - "convertedRgb565" : [ 8452, 21634, 30084, -2556, -15360, -19708, -2146, -2804, -7030, 25092, -19446 ] - }, "tile" : { "width" : 32, "height" : 32, "paletteIndices" : "AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAQEBAQAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAABAQECAgMDAQEAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAQQEAQICAwMDAgEAAAAAAAAAAAAAAAAAAAAAAAAAAAEFBQQEAQICAwICAgEAAAAAAAAAAAAAAAAAAAAAAAAAAQUBBQQFAQICAgIDAQAAAAAAAAAAAAAAAAAAAAAAAAAAAQYBBQUFAQIBAgIDAQAAAAAAAAAAAAAAAAAAAAAAAAABBgcBBQQBAQgBAgMBAAAAAAAAAAAAAAAAAAAAAAAAAAEIAQcBBAEICQECAgEAAAAAAAAAAAAAAAAAAAAAAAABCAgBBwEEAQkGAQICAQAAAAAAAAAAAAAAAAAAAAAAAAABBgkJAQUBBgEFAQIBAAAAAAAAAAAAAAAAAAAAAAAAAAABAQYGAQYBAQEAAQAAAAAAAAAAAAAAAAAAAAAAAAAAAAEHAQEBAQECAQAAAAAAAAAAAAAAAAAAAAAAAAAAAAABAgEBBwMBAwMBAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAEBCQoBBwEDAgEBAAAAAAAAAAAAAAAAAAAAAAAAAAABAgEJCQoBAgIBAQIBAAAAAAAAAAAAAAAAAAAAAAAAAAECAgEBAQICAQECAQEAAAAAAAAAAAAAAAAAAAAAAAAAAAEBAgECAQECAgEBAQAAAAAAAAAAAAAAAAAAAAAAAAAAAQEBAQICAgEBAQoKAQAAAAAAAAAAAAAAAAAAAAAAAAEBAQEBAQEBAQELCwoBAAAAAAAAAAAAAAAAAAAAAAAAAQEBAQEBAQEBAQsLAQEAAAAAAAAAAAAAAAAAAAAAAAAAAQEBAQEBAQEBAQEBAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAEBAQEBAQAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA==" + }, + "palette" : { + "originalArgb8888" : [ -14671840, -11431408, -9326048, -802016, -3964416, -5086944, -789517, -810399, -1863087, -10403552, -5078447 ], + "convertedRgb565" : [ 8452, 21634, 30084, -2556, -15360, -19708, -2146, -2804, -7030, 25092, -19446 ] } }, "diagnostics" : [ ] @@ -1450,14 +1450,14 @@ "last_modified" : 1775797786713, "fingerprint" : "9216dfc6a6226fac398e9f781550d23fbfaa65bd377cdda69187149beca114ec", "metadata" : { - "palette" : { - "originalArgb8888" : [ -14671840, -11431408, -9326048, -802016, -3964416, -5086944, -789517, -810399, -1863087, -10403552, -5078447 ], - "convertedRgb565" : [ 8452, 21634, 30084, -2556, -15360, -19708, -2146, -2804, -7030, 25092, -19446 ] - }, "tile" : { "width" : 32, "height" : 32, "paletteIndices" : "AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAQEBAQAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAEBAQECAgMDAQEAAAEBAAAAAAAAAAAAAAAAAAAAAAABBAQEAQICAwMDAgEBAwEAAAAAAAAAAAAAAAAAAAAAAAEFBQQEAQICAwICAQIDAQAAAAAAAAAAAAAAAAAAAAAAAAEBBQQFAQICAgICAwEBAAAAAAAAAAAAAAAAAAAAAAAAAQYBBQUFAQIBAgICAQAAAAAAAAAAAAAAAAAAAAAAAAABBgcBBQQFAQgBAQEBAAAAAAAAAAAAAAAAAAAAAAAAAAEIAQcBBAUBCQEBBQUBAAAAAAAAAAAAAAAAAAAAAAABCAgBBwgBBAUBAQUBAAAAAAAAAAAAAAAAAAAAAAAAAAABBgkJBgYBAQEBAQAAAAAAAAAAAAAAAAAAAAAAAAAAAAABAQYGBgYBAQAAAAAAAAAAAAAAAAAAAAAAAAAAAAABAQEBAQEBAQMBAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAEJCgEHAwECAwEBAQAAAAAAAAAAAAAAAAAAAAAAAAABAQkKAQcCAQIDAQEBAQAAAAAAAAAAAAAAAAAAAAAAAAEKAQEBAQECAgEBAgELAQAAAAAAAAAAAAAAAAAAAAAAAQEKAQICAQEBAgIBAQoLAQAAAAAAAAAAAAAAAAAAAAAAAQEBAQECAgICAQEAAQEAAAAAAAAAAAAAAAAAAAAAAAAAAQEBAQEBAQEBAQAAAAAAAAAAAAAAAAAAAAAAAAAAAAEBAQEBAQEBAQEBAQAAAAAAAAAAAAAAAAAAAAAAAAAAAQEBAQEBAQEBAQEBAAAAAAAAAAAAAAAAAAAAAAAAAAAAAQEBAQEBAQEBAQAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAEBAQEBAQAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA==" + }, + "palette" : { + "originalArgb8888" : [ -14671840, -11431408, -9326048, -802016, -3964416, -5086944, -789517, -810399, -1863087, -10403552, -5078447 ], + "convertedRgb565" : [ 8452, 21634, 30084, -2556, -15360, -19708, -2146, -2804, -7030, 25092, -19446 ] } }, "diagnostics" : [ ] @@ -1468,14 +1468,14 @@ "last_modified" : 1775797786712, "fingerprint" : "ebc4b7ca7bb1455288681c5d71424f60f658a44cb343d0c3934329cec676c867", "metadata" : { - "palette" : { - "originalArgb8888" : [ -14671840, -11431408, -9326048, -802016, -3964416, -5086944, -789517, -810399, -1863087, -10403552, -5078447 ], - "convertedRgb565" : [ 8452, 21634, 30084, -2556, -15360, -19708, -2146, -2804, -7030, 25092, -19446 ] - }, "tile" : { "width" : 32, "height" : 32, "paletteIndices" : "AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAABAQEBAAAAAAEBAAAAAAAAAAAAAAAAAAAAAAAAAAEBAQICAwMBAQEBAwEAAAAAAAAAAAAAAAAAAAAAAAABBAQBAgIDAwMCAQMDAQAAAAAAAAAAAAAAAAAAAAAAAQUFBAQBAgIDAgICAwIBAAAAAAAAAAAAAAAAAAAAAAABBQEFBAUBAgICAgMCAQAAAAAAAAAAAAAAAAAAAAAAAAABBgEFBQUBAgECAgIBAAAAAAAAAAAAAAAAAAAAAAAAAAEGBwEFBAUBCAEBAQAAAAAAAAAAAAAAAAAAAAAAAAAAAQgBBwEEBQEJAQEAAAAAAAAAAAAAAAAAAAAAAAAAAAEICAEHCQEEBQEFAQAAAAAAAAAAAAAAAAAAAAAAAAAAAQEBCQkGBgEBAQUBAAAAAAAAAAAAAAAAAAAAAAAAAAABCQoBAQEGBgEBAQUBAAAAAAAAAAAAAAAAAAAAAAAAAAEKCgEHAgEBAQMBAQAAAAAAAAAAAAAAAAAAAAAAAAAAAAEBBwICAQIDAwEBAAAAAAAAAAAAAAAAAAAAAAAAAAABAQEBAQECAgMBAQIBAAAAAAAAAAAAAAAAAAAAAAAAAQoBAQIBAgICAgECAQEAAAAAAAAAAAAAAAAAAAAAAAABCgoBAgIBAQEBAgELAQAAAAAAAAAAAAAAAAAAAAAAAAEBAQEBAQICAgIBAQEAAAAAAAAAAAAAAAAAAAAAAAAAAAEBAQEBAQEBAQEBAQAAAAAAAAAAAAAAAAAAAAAAAAAAAQEBAQEBAQEBAQEBAAAAAAAAAAAAAAAAAAAAAAAAAAAAAQEBAQEBAQEBAQAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAEBAQEBAQAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA==" + }, + "palette" : { + "originalArgb8888" : [ -14671840, -11431408, -9326048, -802016, -3964416, -5086944, -789517, -810399, -1863087, -10403552, -5078447 ], + "convertedRgb565" : [ 8452, 21634, 30084, -2556, -15360, -19708, -2146, -2804, -7030, 25092, -19446 ] } }, "diagnostics" : [ ] @@ -1486,14 +1486,14 @@ "last_modified" : 1775797786718, "fingerprint" : "c363f3ef7f32d9b249c7dc8babdb3eb5aae68c524099e5e97290202b054dda71", "metadata" : { - "palette" : { - "originalArgb8888" : [ -14671840, -11431408, -9326048, -802016, -3964416, -5086944, -789517, -810399, -1863087, -10403552, -5078447 ], - "convertedRgb565" : [ 8452, 21634, 30084, -2556, -15360, -19708, -2146, -2804, -7030, 25092, -19446 ] - }, "tile" : { "width" : 32, "height" : 32, "paletteIndices" : "AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAABAQEBAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAEBAQICAwMBAQAAAAAAAAAAAAAAAAAAAAAAAAAAAAABBAQBAgIDAwMCAQAAAAAAAAAAAAAAAAAAAAAAAAAAAQUFBAQBAgIDAgICAQAAAAAAAAAAAAAAAAAAAAAAAAABBQEFBAUBAgICAgMBAAAAAAAAAAAAAAAAAAAAAAAAAAABBgEFBQUBAgECAgMBAAAAAAAAAAAAAAAAAAAAAAAAAAEGBwEFBAEBCAECAwEAAAAAAAAAAAAAAAAAAAAAAAAAAQgBBwEEAQgJAQICAQAAAAAAAAAAAAAAAAAAAAAAAAEICAEHAQQBCQYBAgIBAAAAAAAAAAAAAAAAAAAAAAAAAAEGCQkBBQEGAQUBAgEAAAAAAAAAAAAAAAAAAAAAAAAAAAEBBgYBBgEBAQABAAAAAAAAAAAAAAAAAAAAAAAAAAAAAQcBAQEBAgIBAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAECAwECAwIBAgEAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAQECAQcHBwECAQAAAAAAAAAAAAAAAAAAAAAAAAAAAAABBAEBAQEBAQECAQAAAAAAAAAAAAAAAAAAAAAAAAAAAAABAgEJCgoBAgEAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAQEBAQEJCQEBAQAAAAAAAAAAAAAAAAAAAAAAAAAAAAEBAQEKAQEBAQEBAQAAAAAAAAAAAAAAAAAAAAAAAAAAAQEBAQELCwoKAQEBAAAAAAAAAAAAAAAAAAAAAAAAAAAAAQEBAQEBAQEBAQAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAEBAQEBAQAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA==" + }, + "palette" : { + "originalArgb8888" : [ -14671840, -11431408, -9326048, -802016, -3964416, -5086944, -789517, -810399, -1863087, -10403552, -5078447 ], + "convertedRgb565" : [ 8452, 21634, 30084, -2556, -15360, -19708, -2146, -2804, -7030, 25092, -19446 ] } }, "diagnostics" : [ ] @@ -1504,14 +1504,14 @@ "last_modified" : 1775797786717, "fingerprint" : "1ba8ce75c445396334737143e0cfa56c87a1fb64cca8ad0962192594849249eb", "metadata" : { - "palette" : { - "originalArgb8888" : [ -14671840, -11431408, -9326048, -802016, -3964416, -5086944, -789517, -810399, -1863087, -10403552 ], - "convertedRgb565" : [ 8452, 21634, 30084, -2556, -15360, -19708, -2146, -2804, -7030, 25092 ] - }, "tile" : { "width" : 32, "height" : 32, "paletteIndices" : "AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAABAQEBAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAEBAQICAwMBAQAAAAAAAAAAAAAAAAAAAAAAAAAAAAABBAQBAgIDAwMCAQAAAAAAAAAAAAAAAAAAAAAAAAAAAQUFBAQBAgIDAgICAQAAAAAAAAAAAAAAAAAAAAAAAAABBQEFBAUBAgICAgMBAAAAAAAAAAAAAAAAAAAAAAAAAAABBgEFBQUBAgECAgMBAAAAAAAAAAAAAAAAAAAAAAAAAAEGBwEFBAEBCAECAwEAAAAAAAAAAAAAAAAAAAAAAAAAAQgBBwEEAQgJAQICAQAAAAAAAAAAAAAAAAAAAAAAAAEICAEHAQQBCQYBAgIBAAAAAAAAAAAAAAAAAAAAAAAAAAEGCQkBBQEGAQUBAgEAAAAAAAAAAAAAAAAAAAAAAAAAAAEBBgYBAQEBAQABAAAAAAAAAAAAAAAAAAAAAAAAAAAAAQcBAQEDAQEAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAABAwMBAgcHAQAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAQMDAwIBAQEBAQAAAAAAAAAAAAAAAAAAAAAAAAAAAAABBAIDAgEKCgECAQAAAAAAAAAAAAAAAAAAAAAAAAAAAAECAQEBAQkJAQIBAAAAAAAAAAAAAAAAAAAAAAAAAAAAAQECAgICAQECAQoBAAAAAAAAAAAAAAAAAAAAAAAAAAABAQEBAQICAgEKCgEAAAAAAAAAAAAAAAAAAAAAAAAAAQEBAQEBAQEBCgoKAQAAAAAAAAAAAAAAAAAAAAAAAAABAQEBAQEBAQEBAQEAAAAAAAAAAAAAAAAAAAAAAAAAAAABAQEBAQEBAQEBAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAQEBAQEBAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA==" + }, + "palette" : { + "originalArgb8888" : [ -14671840, -11431408, -9326048, -802016, -3964416, -5086944, -789517, -810399, -1863087, -10403552 ], + "convertedRgb565" : [ 8452, 21634, 30084, -2556, -15360, -19708, -2146, -2804, -7030, 25092 ] } }, "diagnostics" : [ ] @@ -1522,14 +1522,14 @@ "last_modified" : 1775797786714, "fingerprint" : "5e0954447699c6d5eac7550f1a10cf520efcddad0b9fbd9a716434da9d9550d4", "metadata" : { - "palette" : { - "originalArgb8888" : [ -14671840, -11431408, -9326048, -802016, -3964416, -5086944, -789517, -810399, -1863087, -10403552, -5078447 ], - "convertedRgb565" : [ 8452, 21634, 30084, -2556, -15360, -19708, -2146, -2804, -7030, 25092, -19446 ] - }, "tile" : { "width" : 32, "height" : 32, "paletteIndices" : "AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAABAQEBAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAQEBAQICAwMBAQAAAAAAAAAAAAAAAAAAAAAAAAAAAAEEBAQBAgIDAwMCAQABAQAAAAAAAAAAAAAAAAAAAAAAAQUFBAQBAgIDAgIBAQMBAAAAAAAAAAAAAAAAAAAAAAAAAQEFBAUBAgICAgIDAwEAAAAAAAAAAAAAAAAAAAAAAAABBgEFBQUBAgECAgIBAAAAAAAAAAAAAAAAAAAAAAAAAAEGBwEFBAUBCAEBAQEAAAAAAAAAAAAAAAAAAAAAAAAAAQgBBwEEBQEJAQEFBQEAAAAAAAAAAAAAAAAAAAAAAAEICAEHCAEEBQEBBQEBAAAAAAAAAAAAAAAAAAAAAAAAAAEGCQkGBgEBAQEBAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAEBBgYGAQIDAQAAAAAAAAAAAAAAAAAAAAAAAAAAAAABCQEBAQEBAQEHAQAAAAAAAAAAAAAAAAAAAAAAAAAAAQEBBwcDAgEKCgEBAAAAAAAAAAAAAAAAAAAAAAAAAAABAgIBAwMCAQkJAQEAAAAAAAAAAAAAAAAAAAAAAAAAAQEBAQIBAgMCAQEBCgEAAAAAAAAAAAAAAAAAAAAAAAABCwsKAQIBAQECAgEKAQAAAAAAAAAAAAAAAAAAAAAAAAABCwsKAQICAgIBCgoBAAAAAAAAAAAAAAAAAAAAAAAAAAABAQEBAQEBAQEBAQAAAAAAAAAAAAAAAAAAAAAAAAAAAQEBAQEBAQEBAQEBAAAAAAAAAAAAAAAAAAAAAAAAAAABAQEBAQEBAQEBAQEAAAAAAAAAAAAAAAAAAAAAAAAAAAABAQEBAQEBAQEBAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAQEBAQEBAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA==" + }, + "palette" : { + "originalArgb8888" : [ -14671840, -11431408, -9326048, -802016, -3964416, -5086944, -789517, -810399, -1863087, -10403552, -5078447 ], + "convertedRgb565" : [ 8452, 21634, 30084, -2556, -15360, -19708, -2146, -2804, -7030, 25092, -19446 ] } }, "diagnostics" : [ ] @@ -1540,14 +1540,14 @@ "last_modified" : 1775797786716, "fingerprint" : "6104ba7f216a937994d478ed07766ec28f48ad72fdd6620508535a1f877b8ddb", "metadata" : { - "palette" : { - "originalArgb8888" : [ -14671840, -11431408, -9326048, -802016, -3964416, -5086944, -789517, -810399, -1863087, -10403552, -5078447 ], - "convertedRgb565" : [ 8452, 21634, 30084, -2556, -15360, -19708, -2146, -2804, -7030, 25092, -19446 ] - }, "tile" : { "width" : 32, "height" : 32, "paletteIndices" : "AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAABAQEBAAAAAAEBAAAAAAAAAAAAAAAAAAAAAAAAAAEBAQICAwMBAQEBAwEAAAAAAAAAAAAAAAAAAAAAAAABBAQBAgIDAwMCAQMDAQAAAAAAAAAAAAAAAAAAAAAAAQUFBAQBAgIDAgICAwIBAAAAAAAAAAAAAAAAAAAAAAABBQEFBAUBAgICAgMCAQAAAAAAAAAAAAAAAAAAAAAAAAABBgEFBQUBAgECAgIBAAAAAAAAAAAAAAAAAAAAAAAAAAEGBwEFBAUBCAEBAQAAAAAAAAAAAAAAAAAAAAAAAAAAAQgBBwEEBQEJAQEAAAAAAAAAAAAAAAAAAAAAAAAAAAEICAEHCQEEBQEFAQAAAAAAAAAAAAAAAAAAAAAAAAAAAAEGCQkGBgEBAQEBAAAAAAAAAAAAAAAAAAAAAAAAAAABAQEBBgYGAQIDAgEBAAAAAAAAAAAAAAAAAAAAAAAAAAEJAQEBAQEBAgIBAQAAAAAAAAAAAAAAAAAAAAAAAAAAAAEBBwcDAgIBAQoKAQAAAAAAAAAAAAAAAAAAAAAAAAAAAQQBAwMDAgIBCQkBAAAAAAAAAAAAAAAAAAAAAAAAAAEBAgECAwMCAQEBAQEAAAAAAAAAAAAAAAAAAAAAAAABCwYBAgEBAQECAgEKAQAAAAAAAAAAAAAAAAAAAAAAAAELCgYBAgICAgEBAQEAAAAAAAAAAAAAAAAAAAAAAAAAAAEKCgoBAQEBAQEBAQAAAAAAAAAAAAAAAAAAAAAAAAAAAQEBAQEBAQEBAQEBAAAAAAAAAAAAAAAAAAAAAAAAAAAAAQEBAQEBAQEBAQAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAEBAQEBAQAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA==" + }, + "palette" : { + "originalArgb8888" : [ -14671840, -11431408, -9326048, -802016, -3964416, -5086944, -789517, -810399, -1863087, -10403552, -5078447 ], + "convertedRgb565" : [ 8452, 21634, 30084, -2556, -15360, -19708, -2146, -2804, -7030, 25092, -19446 ] } }, "diagnostics" : [ ] @@ -1602,14 +1602,14 @@ "last_modified" : 1776965154257, "fingerprint" : "8771c3e294d0edbc8dd3aaa6995a6db32166ae6bfb3e063170cc79b298d17e71", "metadata" : { - "palette" : { - "originalArgb8888" : [ -12019640 ], - "convertedRgb565" : [ 19657 ] - }, "tile" : { "width" : 8, "height" : 8, "paletteIndices" : "AQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQ==" + }, + "palette" : { + "originalArgb8888" : [ -12019640 ], + "convertedRgb565" : [ 19657 ] } }, "diagnostics" : [ ] @@ -1620,14 +1620,14 @@ "last_modified" : 1776965154257, "fingerprint" : "5d81eef8be13043330b42b546e10beed8ba00dfaa42df67477a8778c2b9484d7", "metadata" : { - "palette" : { - "originalArgb8888" : [ -12019640, -12552128, -14129088, -14133200, -14145496, -7835584, -5730208, -10465232 ], - "convertedRgb565" : [ 19657, 17352, 11080, 10950, 10565, -29816, -21364, 25222 ] - }, "tile" : { "width" : 8, "height" : 8, "paletteIndices" : "AQEBAQEBAQEBAQEBAQICAgECAgICAgICAgMEBQUFBQQDBAUGBgYGBQMEBQYGBwcIAwQFCAYGCAgBAwUFCAgIBw==" + }, + "palette" : { + "originalArgb8888" : [ -12019640, -12552128, -14129088, -14133200, -14145496, -7835584, -5730208, -10465232 ], + "convertedRgb565" : [ 19657, 17352, 11080, 10950, 10565, -29816, -21364, 25222 ] } }, "diagnostics" : [ ] @@ -1638,14 +1638,14 @@ "last_modified" : 1776965154258, "fingerprint" : "3250840c4fe08c134ea966ce7c8fcaccae2c2a45660d7173c5e262a2e5076548", "metadata" : { - "palette" : { - "originalArgb8888" : [ -12552128, -14133200, -14145496, -10465232, -5730208, -7835584 ], - "convertedRgb565" : [ 17352, 10950, 10565, 25222, -21364, -29816 ] - }, "tile" : { "width" : 8, "height" : 8, "paletteIndices" : "AQEBAQECAwMBAQEBAgMEBQEBAQIDBAUFAQIDAwQEBAQDAwYFBQUFBQQGBQUGBgYGBQUFBgYFBQUFBgYGBQUGBg==" + }, + "palette" : { + "originalArgb8888" : [ -12552128, -14133200, -14145496, -10465232, -5730208, -7835584 ], + "convertedRgb565" : [ 17352, 10950, 10565, 25222, -21364, -29816 ] } }, "diagnostics" : [ ] @@ -1656,14 +1656,14 @@ "last_modified" : 1776965154258, "fingerprint" : "fe3ab2b7eb3b10a042de14484d53e718e6b505edb1ad19053668565bfe3a8f25", "metadata" : { - "palette" : { - "originalArgb8888" : [ -14145496, -14133200, -12552128, -5730208, -10465232, -7835584 ], - "convertedRgb565" : [ 10565, 10950, 17352, -21364, 25222, -29816 ] - }, "tile" : { "width" : 8, "height" : 8, "paletteIndices" : "AQECAwMDAwMEBQECAwMDAwQEBQECAwMDBQUFBQEBAgMEBAQEBAYBAQYGBgYEBAYFBAQEBgYEBAQGBgQEBgYGBA==" + }, + "palette" : { + "originalArgb8888" : [ -14145496, -14133200, -12552128, -5730208, -10465232, -7835584 ], + "convertedRgb565" : [ 10565, 10950, 17352, -21364, 25222, -29816 ] } }, "diagnostics" : [ ] @@ -1674,14 +1674,14 @@ "last_modified" : 1776965154259, "fingerprint" : "7fcbf90e1e9a69d6ce3be80ea1901d66c9992f68dc72e4c636dcd2ad52fa2898", "metadata" : { - "palette" : { - "originalArgb8888" : [ -12019640, -12552128, -14133200, -14145496, -14129088, -7835584, -10465232, -5730208 ], - "convertedRgb565" : [ 19657, 17352, 10950, 10565, 11080, -29816, 25222, -21364 ] - }, "tile" : { "width" : 8, "height" : 8, "paletteIndices" : "AQEBAQEBAQECAgIBAQEBAQICAgICAgIBAwQEBAQDBQIEBgYGBgQDBQcICAYGBAMFBwcGBgcEAwUIBwcHBAQFAQ==" + }, + "palette" : { + "originalArgb8888" : [ -12019640, -12552128, -14133200, -14145496, -14129088, -7835584, -10465232, -5730208 ], + "convertedRgb565" : [ 19657, 17352, 10950, 10565, 11080, -29816, 25222, -21364 ] } }, "diagnostics" : [ ] @@ -1692,14 +1692,14 @@ "last_modified" : 1776965154259, "fingerprint" : "451fc8d646049944d5aa7c7dc254636eec0151aaff6e2051059304b9d6ebc31e", "metadata" : { - "palette" : { - "originalArgb8888" : [ -12019640, -14129088, -14133200, -14145496, -10465232, -5730208, -7835584 ], - "convertedRgb565" : [ 19657, 11080, 10950, 10565, 25222, -21364, -29816 ] - }, "tile" : { "width" : 8, "height" : 8, "paletteIndices" : "AQIDBAQFBgYBAQIDBAYGBwEBAQMEBgcHAQEBBAQGBwcBAQQFBAYHBwEEBwUEBgcHBAcGBQQGBwcEBwYFBAYHBw==" + }, + "palette" : { + "originalArgb8888" : [ -12019640, -14129088, -14133200, -14145496, -10465232, -5730208, -7835584 ], + "convertedRgb565" : [ 19657, 11080, 10950, 10565, 25222, -21364, -29816 ] } }, "diagnostics" : [ ] @@ -1710,14 +1710,14 @@ "last_modified" : 1776965154260, "fingerprint" : "aa757df4600823ec6655235a1081061777124ccee74b31481bbe402e53635f53", "metadata" : { - "palette" : { - "originalArgb8888" : [ -7835584, -5730208, -10465232, -14145496 ], - "convertedRgb565" : [ -29816, -21364, 25222, 10565 ] - }, "tile" : { "width" : 8, "height" : 8, "paletteIndices" : "AQECAwMBAQEBAgIBAwMBAgICAQEBAwMCAgIBAQIDBAMCAgEBAgMEBAICAQECAwQEAgIBAQIDBAMCAgIBAwQDAg==" + }, + "palette" : { + "originalArgb8888" : [ -7835584, -5730208, -10465232, -14145496 ], + "convertedRgb565" : [ -29816, -21364, 25222, 10565 ] } }, "diagnostics" : [ ] @@ -1728,14 +1728,14 @@ "last_modified" : 1776965154260, "fingerprint" : "38162157f5685cce25b835d3a2caee3465fd2ec3ee5db2a5089d7d5ae5ea3bb7", "metadata" : { - "palette" : { - "originalArgb8888" : [ -7835584, -10465232, -5730208, -14145496 ], - "convertedRgb565" : [ -29816, 25222, -21364, 10565 ] - }, "tile" : { "width" : 8, "height" : 8, "paletteIndices" : "AQEBAgIDAQEDAQICAQMDAQMCAgEBAQMDAgQCAwEBAwMEBAIDAQEDAwQEAgMBAQMDAgQCAwEBAwMDAgQCAQMDAw==" + }, + "palette" : { + "originalArgb8888" : [ -7835584, -10465232, -5730208, -14145496 ], + "convertedRgb565" : [ -29816, 25222, -21364, 10565 ] } }, "diagnostics" : [ ] @@ -1746,14 +1746,14 @@ "last_modified" : 1776965154260, "fingerprint" : "8cab5b3d553af9ed371bd19fc624763accc90e5d926d300ba31dd8d9d6bab803", "metadata" : { - "palette" : { - "originalArgb8888" : [ -5730208, -10465232, -14145496, -14133200, -14129088, -12019640, -7835584 ], - "convertedRgb565" : [ -21364, 25222, 10565, 10950, 11080, 19657, -29816 ] - }, "tile" : { "width" : 8, "height" : 8, "paletteIndices" : "AQECAwMEBQYHAQEDBAUGBgcHAQMEBgYGBwcBAwMGBgYHBwEDAgMGBgcHAQMCBwMGBwcBAwIBBwMHBwEDAgEHAw==" + }, + "palette" : { + "originalArgb8888" : [ -5730208, -10465232, -14145496, -14133200, -14129088, -12019640, -7835584 ], + "convertedRgb565" : [ -21364, 25222, 10565, 10950, 11080, 19657, -29816 ] } }, "diagnostics" : [ ] @@ -1764,14 +1764,14 @@ "last_modified" : 1776965154261, "fingerprint" : "d9ff5a6df0f65f5fcfb8f22376beeb266d429e2c6e9c82f51c12bc6ee4c3fcdc", "metadata" : { - "palette" : { - "originalArgb8888" : [ -14145496, -10465232, -7835584, -5730208, -14133200, -14129088, -12019640 ], - "convertedRgb565" : [ 10565, 25222, -29816, -21364, 10950, 11080, 19657 ] - }, "tile" : { "width" : 8, "height" : 8, "paletteIndices" : "AQIDAgIBBAMFAQECAgEEBAUGBQECAgEEBwYFBQECAQEHBwYGBQEBAgcHBwYFAQMDBwcHBwEBAwMHBwcFAQICAw==" + }, + "palette" : { + "originalArgb8888" : [ -14145496, -10465232, -7835584, -5730208, -14133200, -14129088, -12019640 ], + "convertedRgb565" : [ 10565, 25222, -29816, -21364, 10950, 11080, 19657 ] } }, "diagnostics" : [ ] @@ -1782,14 +1782,14 @@ "last_modified" : 1776965154261, "fingerprint" : "b9ff45c77f7779a6acebcc537c2ddac0e27e91162b656a04dc4772ec5f24fc26", "metadata" : { - "palette" : { - "originalArgb8888" : [ -7835584, -5730208, -10465232, -14145496 ], - "convertedRgb565" : [ -29816, -21364, 25222, 10565 ] - }, "tile" : { "width" : 8, "height" : 8, "paletteIndices" : "AQICAwMBAQIBAQMDAgIBAQIBAQEBAgIBAgICAgEBAgIEAwMCAgEBAQMEAwMCAgEBAQMEAwMDAgIBAwMEAwMDAw==" + }, + "palette" : { + "originalArgb8888" : [ -7835584, -5730208, -10465232, -14145496 ], + "convertedRgb565" : [ -29816, -21364, 25222, 10565 ] } }, "diagnostics" : [ ] @@ -1800,14 +1800,14 @@ "last_modified" : 1776965154261, "fingerprint" : "43f370324fedccda888d49409e2a64f182f08b4143b4bdd5bafaf498feebd21a", "metadata" : { - "palette" : { - "originalArgb8888" : [ -5730208, -7835584, -10465232, -14145496 ], - "convertedRgb565" : [ -21364, -29816, 25222, 10565 ] - }, "tile" : { "width" : 8, "height" : 8, "paletteIndices" : "AQICAwMBAQICAgEBAwMCAgIBAQICAgIBAQECAgEBAQECAgIBAQMDBAICAQEDAwQDAQEDAwMEAwIDAwMDBAMDAg==" + }, + "palette" : { + "originalArgb8888" : [ -5730208, -7835584, -10465232, -14145496 ], + "convertedRgb565" : [ -21364, -29816, 25222, 10565 ] } }, "diagnostics" : [ ] @@ -1818,14 +1818,14 @@ "last_modified" : 1776965154262, "fingerprint" : "cb047e655f4e196f22ca0048149df5dcb959f895faeaeb94920182d4a2d16b38", "metadata" : { - "palette" : { - "originalArgb8888" : [ -7835584, -5730208, -14145496, -10465232, -14133200, -14129088, -12019640 ], - "convertedRgb565" : [ -29816, -21364, 10565, 25222, 10950, 11080, 19657 ] - }, "tile" : { "width" : 8, "height" : 8, "paletteIndices" : "AQIDBAQBBAMCAgMEBAMDBQIDBAQDBQYFAwMEAwUFBgcEAwMFBgYHBwEBAwUGBwcHAQEDAwcHBwcBBAQDBQcHBw==" + }, + "palette" : { + "originalArgb8888" : [ -7835584, -5730208, -14145496, -10465232, -14133200, -14129088, -12019640 ], + "convertedRgb565" : [ -29816, -21364, 10565, 25222, 10950, 11080, 19657 ] } }, "diagnostics" : [ ] @@ -1836,14 +1836,14 @@ "last_modified" : 1776965154262, "fingerprint" : "25eba17b67dd5159f5fb9d3edd531d54a44d1c76f997385840dac53517b98886", "metadata" : { - "palette" : { - "originalArgb8888" : [ -12019640, -14145496, -7835584, -10465232, -14133200, -14129088 ], - "convertedRgb565" : [ 19657, 10565, -29816, 25222, 10950, 11080 ] - }, "tile" : { "width" : 8, "height" : 8, "paletteIndices" : "AQEBAgMDBAQBAQIDAwMDBAEBAgMDAwMEAQECAwMEAgQBAQIEAgUFAgEBBQUGBQYFAQEBAQEGAQYBAQEBAQEBAQ==" + }, + "palette" : { + "originalArgb8888" : [ -12019640, -14145496, -7835584, -10465232, -14133200, -14129088 ], + "convertedRgb565" : [ 19657, 10565, -29816, 25222, 10950, 11080 ] } }, "diagnostics" : [ ] @@ -1854,14 +1854,14 @@ "last_modified" : 1776965154262, "fingerprint" : "32ca96c14290de8009fd2db623f55514bed2345b7d5881a80dd3fe6235012854", "metadata" : { - "palette" : { - "originalArgb8888" : [ -10465232, -14145496, -14133200, -7835584, -14129088, -12019640 ], - "convertedRgb565" : [ 25222, 10565, 10950, -29816, 11080, 19657 ] - }, "tile" : { "width" : 8, "height" : 8, "paletteIndices" : "AQEBAgEBAgICAQICAQIBAQICAwICAQEEAgMDAwIBAQQDAwUDAwIBAQUFBgUFAgEEBgYGBgYDAgEGBgYGBgYDAg==" + }, + "palette" : { + "originalArgb8888" : [ -10465232, -14145496, -14133200, -7835584, -14129088, -12019640 ], + "convertedRgb565" : [ 25222, 10565, 10950, -29816, 11080, 19657 ] } }, "diagnostics" : [ ] @@ -1872,14 +1872,14 @@ "last_modified" : 1776965154263, "fingerprint" : "7a093fe00c805bcf38d4facff14a6d4c2b8baeaa2d553fa8d3db9f2d76b32f3b", "metadata" : { - "palette" : { - "originalArgb8888" : [ -14145496, -10465232, -7835584, -14133200, -14129088, -12019640 ], - "convertedRgb565" : [ 10565, 25222, -29816, 10950, 11080, 19657 ] - }, "tile" : { "width" : 8, "height" : 8, "paletteIndices" : "AQECAgECAgICAgECAQECAQMCAgEBBAEBAwICAQQEBAECAgEEBAUEBAMCAQUFBgUFAgEEBgYGBgYBBAYGBgYGBg==" + }, + "palette" : { + "originalArgb8888" : [ -14145496, -10465232, -7835584, -14133200, -14129088, -12019640 ], + "convertedRgb565" : [ 10565, 25222, -29816, 10950, 11080, 19657 ] } }, "diagnostics" : [ ] @@ -1890,14 +1890,14 @@ "last_modified" : 1776965154263, "fingerprint" : "77c5277220421226d16f58b1bcfb4eaf157fa4f6c740c5aaebefaf88fb91c22e", "metadata" : { - "palette" : { - "originalArgb8888" : [ -10465232, -7835584, -14145496, -12019640, -14133200, -14129088 ], - "convertedRgb565" : [ 25222, -29816, 10565, 19657, 10950, 11080 ] - }, "tile" : { "width" : 8, "height" : 8, "paletteIndices" : "AQECAgMEBAQBAgICAgMEBAECAgICAwQEAQMBAgIDBAQDBQUDAQMEBAUGBQYFBQQEBgQGBAQEBAQEBAQEBAQEBA==" + }, + "palette" : { + "originalArgb8888" : [ -10465232, -7835584, -14145496, -12019640, -14133200, -14129088 ], + "convertedRgb565" : [ 25222, -29816, 10565, 19657, 10950, 11080 ] } }, "diagnostics" : [ ] diff --git a/tools/vscode-extension/README.md b/tools/vscode-extension/README.md index 92b247c6..7c647b1e 100644 --- a/tools/vscode-extension/README.md +++ b/tools/vscode-extension/README.md @@ -7,7 +7,7 @@ This extension does **not** start the language server itself. It connects to the ```text VS Code Extension -> vscode-languageclient - -> TCP 127.0.0.1:7777 + -> TCP 127.0.0.1:7775 -> Prometeu Studio Java/LSP4J ``` @@ -21,7 +21,7 @@ VS Code Extension The Studio LSP server must be listening on: ```text -127.0.0.1:7777 +127.0.0.1:7775 ``` ## Install dependencies @@ -80,7 +80,7 @@ View -> Output -> Prometeu LSP ```text Prometeu VS Code extension activated. -Connecting to Prometeu Studio LSP at 127.0.0.1:7777... +Connecting to Prometeu Studio LSP at 127.0.0.1:7775... TCP connection established with Prometeu Studio. Prometeu Studio LSP client started. [Info] Hello from Prometeu Studio LSP @@ -136,7 +136,7 @@ Default settings: ```json { "prometeu.studio.host": "127.0.0.1", - "prometeu.studio.port": 7777 + "prometeu.studio.port": 7775 } ``` diff --git a/tools/vscode-extension/package.json b/tools/vscode-extension/package.json index 6a81ca6f..8621202e 100644 --- a/tools/vscode-extension/package.json +++ b/tools/vscode-extension/package.json @@ -48,7 +48,7 @@ }, "prometeu.studio.port": { "type": "number", - "default": 7777, + "default": 7775, "description": "Prometeu Studio LSP TCP port." } } @@ -66,4 +66,4 @@ "@types/vscode": "^1.90.0", "typescript": "^5.0.0" } -} \ No newline at end of file +} diff --git a/tools/vscode-extension/src/extension.ts b/tools/vscode-extension/src/extension.ts index 78d98646..82e99904 100644 --- a/tools/vscode-extension/src/extension.ts +++ b/tools/vscode-extension/src/extension.ts @@ -2,16 +2,25 @@ import * as net from "node:net"; import * as vscode from "vscode"; import { + CloseAction, + ErrorAction, LanguageClient, LanguageClientOptions, ServerOptions, + State, StreamInfo } from "vscode-languageclient/node"; let client: LanguageClient | undefined; let output: vscode.OutputChannel; +let reconnectTimer: NodeJS.Timeout | undefined; +let reconnectContext: vscode.ExtensionContext | undefined; +let stoppingClient = false; + +const RECONNECT_DELAY_MS = 2000; export function activate(context: vscode.ExtensionContext): void { + reconnectContext = context; output = vscode.window.createOutputChannel("Prometeu LSP"); output.appendLine("Prometeu VS Code extension activated."); @@ -40,6 +49,8 @@ export async function deactivate(): Promise { } async function startClient(context: vscode.ExtensionContext): Promise { + clearReconnectTimer(); + if (client) { output.appendLine("Prometeu LSP client is already running."); return; @@ -48,7 +59,7 @@ async function startClient(context: vscode.ExtensionContext): Promise { const config = vscode.workspace.getConfiguration("prometeu.studio"); const host = config.get("host", "127.0.0.1"); - const port = config.get("port", 7777); + const port = config.get("port", 7775); output.show(true); output.appendLine(`Connecting to Prometeu Studio LSP at ${host}:${port}...`); @@ -114,38 +125,66 @@ async function startClient(context: vscode.ExtensionContext): Promise { clientKind: "vscode", prometeuClientVersion: context.extension.packageJSON.version }, - outputChannel: output + outputChannel: output, + errorHandler: { + error: (error) => { + output.appendLine(`Prometeu LSP transport error: ${error.message}`); + return { action: ErrorAction.Continue }; + }, + closed: () => { + output.appendLine("Prometeu LSP transport closed."); + return { action: CloseAction.DoNotRestart }; + } + } }; - client = new LanguageClient( + const nextClient = new LanguageClient( "prometeuStudioLsp", "Prometeu Studio LSP", serverOptions, clientOptions ); + client = nextClient; + nextClient.onDidChangeState((event) => { + output.appendLine(`Prometeu LSP state changed: ${State[event.oldState]} -> ${State[event.newState]}`); + if (event.newState !== State.Stopped) { + return; + } + if (client === nextClient) { + client = undefined; + } + if (!stoppingClient) { + scheduleReconnect(); + } + }); try { - await client.start(); + await nextClient.start(); output.appendLine("Prometeu Studio LSP client started."); vscode.window.showInformationMessage("Connected to Prometeu Studio LSP."); } catch (error) { - client = undefined; + if (client === nextClient) { + client = undefined; + } const message = error instanceof Error ? error.message : String(error); output.appendLine(`Failed to start Prometeu LSP client: ${message}`); vscode.window.showErrorMessage(`Could not connect to Prometeu Studio LSP: ${message}`); + scheduleReconnect(); } } async function stopClient(): Promise { + clearReconnectTimer(); if (!client) { return; } const currentClient = client; client = undefined; + stoppingClient = true; output.appendLine("Stopping Prometeu Studio LSP client..."); @@ -155,5 +194,29 @@ async function stopClient(): Promise { } catch (error) { const message = error instanceof Error ? error.message : String(error); output.appendLine(`Failed to stop Prometeu LSP client cleanly: ${message}`); + } finally { + stoppingClient = false; } -} \ No newline at end of file +} + +function scheduleReconnect(): void { + if (!reconnectContext) { + return; + } + if (reconnectTimer || client) { + return; + } + output.appendLine(`Scheduling Prometeu LSP reconnect in ${RECONNECT_DELAY_MS}ms...`); + reconnectTimer = setTimeout(() => { + reconnectTimer = undefined; + void startClient(reconnectContext!); + }, RECONNECT_DELAY_MS); +} + +function clearReconnectTimer(): void { + if (!reconnectTimer) { + return; + } + clearTimeout(reconnectTimer); + reconnectTimer = undefined; +} -- 2.47.2 From 2994bc67a3abcfd4ce13670dcb4a7b12b18b4a8f Mon Sep 17 00:00:00 2001 From: bQUARKz Date: Wed, 6 May 2026 04:15:36 +0100 Subject: [PATCH 15/37] refactor and clean up --- .../studio/lsp/messages/DocumentPosition.java | 6 ++ .../CompilerLanguageServiceBridge.java | 60 +------------------ .../compiler/DocumentPositionMapper.java | 57 ++++++++++++++++++ 3 files changed, 65 insertions(+), 58 deletions(-) create mode 100644 prometeu-lsp/prometeu-lsp-v1/src/main/java/p/studio/lsp/messages/DocumentPosition.java create mode 100644 prometeu-lsp/prometeu-lsp-v1/src/main/java/p/studio/lsp/services/compiler/DocumentPositionMapper.java diff --git a/prometeu-lsp/prometeu-lsp-v1/src/main/java/p/studio/lsp/messages/DocumentPosition.java b/prometeu-lsp/prometeu-lsp-v1/src/main/java/p/studio/lsp/messages/DocumentPosition.java new file mode 100644 index 00000000..b3ab68ef --- /dev/null +++ b/prometeu-lsp/prometeu-lsp-v1/src/main/java/p/studio/lsp/messages/DocumentPosition.java @@ -0,0 +1,6 @@ +package p.studio.lsp.messages; + +public record DocumentPosition( + int line, + int character) { +} diff --git a/prometeu-lsp/prometeu-lsp-v1/src/main/java/p/studio/lsp/services/compiler/CompilerLanguageServiceBridge.java b/prometeu-lsp/prometeu-lsp-v1/src/main/java/p/studio/lsp/services/compiler/CompilerLanguageServiceBridge.java index 07b5cec2..1ff405ee 100644 --- a/prometeu-lsp/prometeu-lsp-v1/src/main/java/p/studio/lsp/services/compiler/CompilerLanguageServiceBridge.java +++ b/prometeu-lsp/prometeu-lsp-v1/src/main/java/p/studio/lsp/services/compiler/CompilerLanguageServiceBridge.java @@ -1,5 +1,6 @@ package p.studio.lsp.services.compiler; +import org.apache.commons.lang3.StringUtils; import p.studio.compiler.messages.BuilderPipelineConfig; import p.studio.compiler.messages.BuildingIssue; import p.studio.compiler.models.AnalysisSnapshot; @@ -12,7 +13,6 @@ import p.studio.lsp.services.LanguageServiceBridge; import p.studio.utilities.logs.LogAggregator; import java.net.URI; -import java.nio.charset.StandardCharsets; import java.nio.file.Path; import java.util.ArrayList; import java.util.List; @@ -37,7 +37,7 @@ public record CompilerLanguageServiceBridge() implements LanguageServiceBridge { final String text) { Objects.requireNonNull(context, "context"); final Path documentPath = normalizeDocumentPath(documentUri); - final String effectiveText = text == null ? "" : text; + final String effectiveText = StringUtils.isBlank(text) ? "" : text; final AnalysisSnapshot snapshot = analyzeProject(context, Map.of(documentPath, effectiveText)); return new BaselineDocumentAnalysis(mapDiagnostics(snapshot, documentPath, effectiveText)); } @@ -121,60 +121,4 @@ public record CompilerLanguageServiceBridge() implements LanguageServiceBridge { private Path normalizeDocumentPath(final String documentUri) { return Path.of(URI.create(Objects.requireNonNull(documentUri, "documentUri"))).toAbsolutePath().normalize(); } - - private record DocumentPosition( - int line, - int character) { - } - - private static final class DocumentPositionMapper { - private final String text; - - private DocumentPositionMapper(final String text) { - this.text = Objects.requireNonNull(text, "text"); - } - - private DocumentPosition positionOf(final Integer byteOffset) { - if (byteOffset == null || byteOffset <= 0 || text.isEmpty()) { - return new DocumentPosition(0, 0); - } - final int target = Math.min(byteOffset, text.getBytes(StandardCharsets.UTF_8).length); - int utf8Offset = 0; - int line = 0; - int character = 0; - for (int index = 0; index < text.length(); ) { - if (utf8Offset >= target) { - return new DocumentPosition(line, character); - } - final int codePoint = text.codePointAt(index); - final int utf16Width = Character.charCount(codePoint); - final int utf8Width = utf8Length(codePoint); - if (utf8Offset + utf8Width > target) { - return new DocumentPosition(line, character); - } - utf8Offset += utf8Width; - if (codePoint == '\n') { - line++; - character = 0; - } else { - character += utf16Width; - } - index += utf16Width; - } - return new DocumentPosition(line, character); - } - - private int utf8Length(final int codePoint) { - if (codePoint <= 0x7F) { - return 1; - } - if (codePoint <= 0x7FF) { - return 2; - } - if (codePoint <= 0xFFFF) { - return 3; - } - return 4; - } - } } diff --git a/prometeu-lsp/prometeu-lsp-v1/src/main/java/p/studio/lsp/services/compiler/DocumentPositionMapper.java b/prometeu-lsp/prometeu-lsp-v1/src/main/java/p/studio/lsp/services/compiler/DocumentPositionMapper.java new file mode 100644 index 00000000..7c791003 --- /dev/null +++ b/prometeu-lsp/prometeu-lsp-v1/src/main/java/p/studio/lsp/services/compiler/DocumentPositionMapper.java @@ -0,0 +1,57 @@ +package p.studio.lsp.services.compiler; + +import p.studio.lsp.messages.DocumentPosition; + +import java.nio.charset.StandardCharsets; +import java.util.Objects; + +final class DocumentPositionMapper { + private final String text; + + DocumentPositionMapper(final String text) { + this.text = Objects.requireNonNull(text, "text"); + } + + DocumentPosition positionOf(final Integer byteOffset) { + if (byteOffset == null || byteOffset <= 0 || text.isEmpty()) { + return new DocumentPosition(0, 0); + } + final int target = Math.min(byteOffset, text.getBytes(StandardCharsets.UTF_8).length); + int utf8Offset = 0; + int line = 0; + int character = 0; + for (int index = 0; index < text.length(); ) { + if (utf8Offset >= target) { + return new DocumentPosition(line, character); + } + final int codePoint = text.codePointAt(index); + final int utf16Width = Character.charCount(codePoint); + final int utf8Width = utf8Length(codePoint); + if (utf8Offset + utf8Width > target) { + return new DocumentPosition(line, character); + } + utf8Offset += utf8Width; + if (codePoint == '\n') { + line++; + character = 0; + } else { + character += utf16Width; + } + index += utf16Width; + } + return new DocumentPosition(line, character); + } + + private int utf8Length(final int codePoint) { + if (codePoint <= 0x7F) { + return 1; + } + if (codePoint <= 0x7FF) { + return 2; + } + if (codePoint <= 0xFFFF) { + return 3; + } + return 4; + } +} \ No newline at end of file -- 2.47.2 From 0cafe84da0e9e555e8975c6b94f4684da80c0a9f Mon Sep 17 00:00:00 2001 From: bQUARKz Date: Wed, 6 May 2026 09:41:36 +0100 Subject: [PATCH 16/37] 1st semantic version deployed --- prometeu-lsp/prometeu-lsp-v1/build.gradle.kts | 1 + .../lsp/messages/BaselineSemanticToken.java | 33 +++++ .../lsp/messages/BaselineSemanticTokens.java | 14 ++ .../messages/BaselineServerDescription.java | 5 +- .../lsp/services/LanguageServiceBridge.java | 3 + .../CompilerLanguageServiceBridge.java | 71 +++++++++- .../protocol/PrometeuTextDocumentService.java | 21 ++- .../mapping/Lsp4jProtocolMessageMapper.java | 36 +++++ .../mapping/ProtocolMessageMapper.java | 4 + .../CompilerLanguageServiceBridgeTest.java | 17 +++ .../protocol/PrometeuLanguageServerTest.java | 14 +- tools/vscode-extension/package.json | 133 ++++++++++++++++++ 12 files changed, 347 insertions(+), 5 deletions(-) create mode 100644 prometeu-lsp/prometeu-lsp-v1/src/main/java/p/studio/lsp/messages/BaselineSemanticToken.java create mode 100644 prometeu-lsp/prometeu-lsp-v1/src/main/java/p/studio/lsp/messages/BaselineSemanticTokens.java diff --git a/prometeu-lsp/prometeu-lsp-v1/build.gradle.kts b/prometeu-lsp/prometeu-lsp-v1/build.gradle.kts index e73cc24e..a7ccc7b3 100644 --- a/prometeu-lsp/prometeu-lsp-v1/build.gradle.kts +++ b/prometeu-lsp/prometeu-lsp-v1/build.gradle.kts @@ -6,5 +6,6 @@ dependencies { implementation(project(":prometeu-lsp:prometeu-lsp-api")) implementation(project(":prometeu-compiler:prometeu-compiler-core")) implementation(project(":prometeu-compiler:prometeu-build-pipeline")) + implementation(project(":prometeu-compiler:frontends:prometeu-frontend-pbs")) implementation(libs.lsp4j) } diff --git a/prometeu-lsp/prometeu-lsp-v1/src/main/java/p/studio/lsp/messages/BaselineSemanticToken.java b/prometeu-lsp/prometeu-lsp-v1/src/main/java/p/studio/lsp/messages/BaselineSemanticToken.java new file mode 100644 index 00000000..f7efb7e5 --- /dev/null +++ b/prometeu-lsp/prometeu-lsp-v1/src/main/java/p/studio/lsp/messages/BaselineSemanticToken.java @@ -0,0 +1,33 @@ +package p.studio.lsp.messages; + +import java.util.Objects; + +public record BaselineSemanticToken( + int line, + int startCharacter, + int length, + String semanticKey) { + + public BaselineSemanticToken { + if (line < 0) { + throw new IllegalArgumentException("line must be >= 0"); + } + if (startCharacter < 0) { + throw new IllegalArgumentException("startCharacter must be >= 0"); + } + if (length <= 0) { + throw new IllegalArgumentException("length must be > 0"); + } + semanticKey = requireText(semanticKey, "semanticKey"); + } + + private static String requireText( + final String value, + final String field) { + final String candidate = Objects.requireNonNull(value, field).trim(); + if (candidate.isEmpty()) { + throw new IllegalArgumentException(field + " must not be blank"); + } + return candidate; + } +} diff --git a/prometeu-lsp/prometeu-lsp-v1/src/main/java/p/studio/lsp/messages/BaselineSemanticTokens.java b/prometeu-lsp/prometeu-lsp-v1/src/main/java/p/studio/lsp/messages/BaselineSemanticTokens.java new file mode 100644 index 00000000..b20f4d35 --- /dev/null +++ b/prometeu-lsp/prometeu-lsp-v1/src/main/java/p/studio/lsp/messages/BaselineSemanticTokens.java @@ -0,0 +1,14 @@ +package p.studio.lsp.messages; + +import java.util.List; +import java.util.Objects; + +public record BaselineSemanticTokens( + List legend, + List tokens) { + + public BaselineSemanticTokens { + legend = List.copyOf(Objects.requireNonNull(legend, "legend")); + tokens = List.copyOf(Objects.requireNonNull(tokens, "tokens")); + } +} diff --git a/prometeu-lsp/prometeu-lsp-v1/src/main/java/p/studio/lsp/messages/BaselineServerDescription.java b/prometeu-lsp/prometeu-lsp-v1/src/main/java/p/studio/lsp/messages/BaselineServerDescription.java index 2fc747a9..af31b775 100644 --- a/prometeu-lsp/prometeu-lsp-v1/src/main/java/p/studio/lsp/messages/BaselineServerDescription.java +++ b/prometeu-lsp/prometeu-lsp-v1/src/main/java/p/studio/lsp/messages/BaselineServerDescription.java @@ -1,15 +1,18 @@ package p.studio.lsp.messages; import java.util.Objects; +import java.util.List; public record BaselineServerDescription( String name, String version, - boolean hoverSupported) { + boolean hoverSupported, + List semanticTokenTypes) { public BaselineServerDescription { name = requireText(name, "name"); version = requireText(version, "version"); + semanticTokenTypes = List.copyOf(Objects.requireNonNull(semanticTokenTypes, "semanticTokenTypes")); } private static String requireText( diff --git a/prometeu-lsp/prometeu-lsp-v1/src/main/java/p/studio/lsp/services/LanguageServiceBridge.java b/prometeu-lsp/prometeu-lsp-v1/src/main/java/p/studio/lsp/services/LanguageServiceBridge.java index 3b7f982b..aa1ea97d 100644 --- a/prometeu-lsp/prometeu-lsp-v1/src/main/java/p/studio/lsp/services/LanguageServiceBridge.java +++ b/prometeu-lsp/prometeu-lsp-v1/src/main/java/p/studio/lsp/services/LanguageServiceBridge.java @@ -2,6 +2,7 @@ package p.studio.lsp.services; import p.studio.lsp.messages.BaselineDocumentAnalysis; import p.studio.lsp.messages.BaselineHover; +import p.studio.lsp.messages.BaselineSemanticTokens; import p.studio.lsp.messages.BaselineServerDescription; import p.studio.lsp.messages.LspProjectContext; @@ -12,5 +13,7 @@ public interface LanguageServiceBridge { BaselineHover hover(LspProjectContext context, String documentUri, int line, int character); + BaselineSemanticTokens semanticTokens(LspProjectContext context, String documentUri, String text); + String onSave(LspProjectContext context, String documentUri); } diff --git a/prometeu-lsp/prometeu-lsp-v1/src/main/java/p/studio/lsp/services/compiler/CompilerLanguageServiceBridge.java b/prometeu-lsp/prometeu-lsp-v1/src/main/java/p/studio/lsp/services/compiler/CompilerLanguageServiceBridge.java index 1ff405ee..c3a7c27f 100644 --- a/prometeu-lsp/prometeu-lsp-v1/src/main/java/p/studio/lsp/services/compiler/CompilerLanguageServiceBridge.java +++ b/prometeu-lsp/prometeu-lsp-v1/src/main/java/p/studio/lsp/services/compiler/CompilerLanguageServiceBridge.java @@ -5,12 +5,18 @@ import p.studio.compiler.messages.BuilderPipelineConfig; import p.studio.compiler.messages.BuildingIssue; import p.studio.compiler.models.AnalysisSnapshot; import p.studio.compiler.models.BuilderPipelineContext; +import p.studio.compiler.PBSDefinitions; +import p.studio.compiler.pbs.PbsSemanticKind; +import p.studio.compiler.pbs.lexer.PbsLexer; +import p.studio.compiler.pbs.lexer.PbsToken; import p.studio.compiler.source.identifiers.FileId; +import p.studio.compiler.source.diagnostics.DiagnosticSink; import p.studio.compiler.utilities.SourceProviderFactory; import p.studio.compiler.workspaces.BuilderPipelineService; import p.studio.lsp.messages.*; import p.studio.lsp.services.LanguageServiceBridge; import p.studio.utilities.logs.LogAggregator; +import p.studio.utilities.structures.ReadOnlyList; import java.net.URI; import java.nio.file.Path; @@ -27,7 +33,8 @@ public record CompilerLanguageServiceBridge() implements LanguageServiceBridge { return new BaselineServerDescription( "Prometeu Studio LSP", "0.1.0", - true); + true, + PBSDefinitions.PBS.getSemanticPresentation().semanticKeys()); } @Override @@ -58,6 +65,37 @@ public record CompilerLanguageServiceBridge() implements LanguageServiceBridge { """); } + @Override + public BaselineSemanticTokens semanticTokens( + final LspProjectContext context, + final String documentUri, + final String text) { + Objects.requireNonNull(context, "context"); + final String effectiveText = text == null ? "" : text; + final var legend = PBSDefinitions.PBS.getSemanticPresentation().semanticKeys(); + final var tokens = PbsLexer.lex(effectiveText, FileId.none(), DiagnosticSink.empty()); + final var positionMapper = new DocumentPositionMapper(effectiveText); + final var semanticTokens = new ArrayList(); + + for (int index = 0; index < tokens.size(); index += 1) { + final PbsToken token = tokens.get(index); + final PbsSemanticKind semanticKind = classifyToken(tokens, index); + if (semanticKind == null) { + continue; + } + final DocumentPosition start = positionMapper.positionOf(token.start()); + final DocumentPosition end = positionMapper.positionOf(token.end()); + final int length = Math.max(1, end.character() - start.character()); + semanticTokens.add(new BaselineSemanticToken( + start.line(), + start.character(), + length, + semanticKind.semanticKey())); + } + + return new BaselineSemanticTokens(legend, semanticTokens); + } + @Override public String onSave( final LspProjectContext context, @@ -121,4 +159,35 @@ public record CompilerLanguageServiceBridge() implements LanguageServiceBridge { private Path normalizeDocumentPath(final String documentUri) { return Path.of(URI.create(Objects.requireNonNull(documentUri, "documentUri"))).toAbsolutePath().normalize(); } + + private PbsSemanticKind classifyToken( + final ReadOnlyList tokens, + final int index) { + final PbsToken token = tokens.get(index); + final PbsSemanticKind lexicalKind = PbsSemanticKind.forToken(token); + if (lexicalKind != null) { + return lexicalKind; + } + if (token.kind() == p.studio.compiler.pbs.lexer.PbsTokenKind.IDENTIFIER) { + if (isLifecycleToken(tokens, index, token)) { + return PbsSemanticKind.LIFECYCLE; + } + return PbsSemanticKind.IDENTIFIER; + } + return null; + } + + private boolean isLifecycleToken( + final ReadOnlyList tokens, + final int index, + final PbsToken token) { + if (!"Init".equals(token.lexeme()) && !"Frame".equals(token.lexeme())) { + return false; + } + if (index == 0 || index + 1 >= tokens.size()) { + return false; + } + return tokens.get(index - 1).kind() == p.studio.compiler.pbs.lexer.PbsTokenKind.LEFT_BRACKET + && tokens.get(index + 1).kind() == p.studio.compiler.pbs.lexer.PbsTokenKind.RIGHT_BRACKET; + } } diff --git a/prometeu-lsp/prometeu-lsp-v1/src/main/java/p/studio/lsp/services/protocol/PrometeuTextDocumentService.java b/prometeu-lsp/prometeu-lsp-v1/src/main/java/p/studio/lsp/services/protocol/PrometeuTextDocumentService.java index 903bab5f..184f4054 100644 --- a/prometeu-lsp/prometeu-lsp-v1/src/main/java/p/studio/lsp/services/protocol/PrometeuTextDocumentService.java +++ b/prometeu-lsp/prometeu-lsp-v1/src/main/java/p/studio/lsp/services/protocol/PrometeuTextDocumentService.java @@ -8,12 +8,15 @@ import p.studio.lsp.services.LanguageServiceBridge; import p.studio.lsp.services.protocol.mapping.ProtocolMessageMapper; import java.util.Objects; +import java.util.concurrent.ConcurrentHashMap; import java.util.concurrent.CompletableFuture; +import java.util.concurrent.ConcurrentMap; public final class PrometeuTextDocumentService implements TextDocumentService { private final LspProjectContext project; private final LanguageServiceBridge languageServiceBridge; private final ProtocolMessageMapper protocolMessageMapper; + private final ConcurrentMap documentTextByUri = new ConcurrentHashMap<>(); private volatile LanguageClient client; public PrometeuTextDocumentService( @@ -31,19 +34,25 @@ public final class PrometeuTextDocumentService implements TextDocumentService { @Override public void didOpen(final DidOpenTextDocumentParams params) { - publishAnalysis(params.getTextDocument().getUri(), params.getTextDocument().getText()); + final String uri = params.getTextDocument().getUri(); + final String text = params.getTextDocument().getText(); + documentTextByUri.put(uri, text); + publishAnalysis(uri, text); } @Override public void didChange(final DidChangeTextDocumentParams params) { + final String uri = params.getTextDocument().getUri(); final String text = params.getContentChanges().isEmpty() ? "" : params.getContentChanges().getFirst().getText(); - publishAnalysis(params.getTextDocument().getUri(), text); + documentTextByUri.put(uri, text); + publishAnalysis(uri, text); } @Override public void didClose(final DidCloseTextDocumentParams params) { + documentTextByUri.remove(params.getTextDocument().getUri()); final LanguageClient currentClient = client; if (currentClient == null) { return; @@ -70,6 +79,14 @@ public final class PrometeuTextDocumentService implements TextDocumentService { params.getPosition().getCharacter()))); } + @Override + public CompletableFuture semanticTokensFull(final SemanticTokensParams params) { + final String uri = params.getTextDocument().getUri(); + final String text = documentTextByUri.getOrDefault(uri, ""); + return CompletableFuture.completedFuture(protocolMessageMapper.mapSemanticTokens( + languageServiceBridge.semanticTokens(project, uri, text))); + } + private void publishAnalysis( final String uri, final String text) { diff --git a/prometeu-lsp/prometeu-lsp-v1/src/main/java/p/studio/lsp/services/protocol/mapping/Lsp4jProtocolMessageMapper.java b/prometeu-lsp/prometeu-lsp-v1/src/main/java/p/studio/lsp/services/protocol/mapping/Lsp4jProtocolMessageMapper.java index 29079505..28d8cf8d 100644 --- a/prometeu-lsp/prometeu-lsp-v1/src/main/java/p/studio/lsp/services/protocol/mapping/Lsp4jProtocolMessageMapper.java +++ b/prometeu-lsp/prometeu-lsp-v1/src/main/java/p/studio/lsp/services/protocol/mapping/Lsp4jProtocolMessageMapper.java @@ -3,6 +3,8 @@ package p.studio.lsp.services.protocol.mapping; import org.eclipse.lsp4j.*; import p.studio.lsp.messages.*; +import java.util.ArrayList; +import java.util.Comparator; import java.util.List; public final class Lsp4jProtocolMessageMapper implements ProtocolMessageMapper { @@ -20,6 +22,10 @@ public final class Lsp4jProtocolMessageMapper implements ProtocolMessageMapper { capabilities.setTextDocumentSync(syncOptions); capabilities.setHoverProvider(description.hoverSupported()); + final SemanticTokensWithRegistrationOptions semanticTokens = new SemanticTokensWithRegistrationOptions(); + semanticTokens.setLegend(new SemanticTokensLegend(description.semanticTokenTypes(), List.of())); + semanticTokens.setFull(true); + capabilities.setSemanticTokensProvider(semanticTokens); final InitializeResult result = new InitializeResult(capabilities); final ServerInfo serverInfo = new ServerInfo(); @@ -52,6 +58,36 @@ public final class Lsp4jProtocolMessageMapper implements ProtocolMessageMapper { return result; } + @Override + public SemanticTokens mapSemanticTokens(final BaselineSemanticTokens semanticTokens) { + final List orderedTokens = new ArrayList<>(semanticTokens.tokens()); + orderedTokens.sort(Comparator + .comparingInt(BaselineSemanticToken::line) + .thenComparingInt(BaselineSemanticToken::startCharacter)); + + final List data = new ArrayList<>(); + int previousLine = 0; + int previousCharacter = 0; + for (final BaselineSemanticToken token : orderedTokens) { + final int deltaLine = token.line() - previousLine; + final int deltaStart = deltaLine == 0 + ? token.startCharacter() - previousCharacter + : token.startCharacter(); + final int tokenType = semanticTokens.legend().indexOf(token.semanticKey()); + if (tokenType < 0) { + continue; + } + data.add(deltaLine); + data.add(deltaStart); + data.add(token.length()); + data.add(tokenType); + data.add(0); + previousLine = token.line(); + previousCharacter = token.startCharacter(); + } + return new SemanticTokens(data); + } + @Override public MessageParams mapInfoMessage(final String message) { return new MessageParams(MessageType.Info, message); diff --git a/prometeu-lsp/prometeu-lsp-v1/src/main/java/p/studio/lsp/services/protocol/mapping/ProtocolMessageMapper.java b/prometeu-lsp/prometeu-lsp-v1/src/main/java/p/studio/lsp/services/protocol/mapping/ProtocolMessageMapper.java index ad69e8c0..18172125 100644 --- a/prometeu-lsp/prometeu-lsp-v1/src/main/java/p/studio/lsp/services/protocol/mapping/ProtocolMessageMapper.java +++ b/prometeu-lsp/prometeu-lsp-v1/src/main/java/p/studio/lsp/services/protocol/mapping/ProtocolMessageMapper.java @@ -4,8 +4,10 @@ import org.eclipse.lsp4j.Hover; import org.eclipse.lsp4j.InitializeResult; import org.eclipse.lsp4j.MessageParams; import org.eclipse.lsp4j.PublishDiagnosticsParams; +import org.eclipse.lsp4j.SemanticTokens; import p.studio.lsp.messages.BaselineDocumentAnalysis; import p.studio.lsp.messages.BaselineHover; +import p.studio.lsp.messages.BaselineSemanticTokens; import p.studio.lsp.messages.BaselineServerDescription; public interface ProtocolMessageMapper { @@ -17,6 +19,8 @@ public interface ProtocolMessageMapper { Hover mapHover(BaselineHover hover); + SemanticTokens mapSemanticTokens(BaselineSemanticTokens semanticTokens); + MessageParams mapInfoMessage(String message); MessageParams mapErrorMessage(String message); MessageParams mapWarningMessage(String message); diff --git a/prometeu-lsp/prometeu-lsp-v1/src/test/java/p/studio/lsp/services/compiler/CompilerLanguageServiceBridgeTest.java b/prometeu-lsp/prometeu-lsp-v1/src/test/java/p/studio/lsp/services/compiler/CompilerLanguageServiceBridgeTest.java index 1aa1be51..c95d6c36 100644 --- a/prometeu-lsp/prometeu-lsp-v1/src/test/java/p/studio/lsp/services/compiler/CompilerLanguageServiceBridgeTest.java +++ b/prometeu-lsp/prometeu-lsp-v1/src/test/java/p/studio/lsp/services/compiler/CompilerLanguageServiceBridgeTest.java @@ -38,6 +38,23 @@ class CompilerLanguageServiceBridgeTest { assertTrue(analysis.issues().stream().noneMatch(issue -> issue.message().contains("Compiler-backed baseline"))); } + @Test + void semanticTokensReturnsPbsLegendAndTokens() { + final CompilerLanguageServiceBridge bridge = new CompilerLanguageServiceBridge(); + final var semanticTokens = bridge.semanticTokens( + new LspProjectContext("main", "pbs", Path.of(".")), + Path.of("demo.pbs").toUri().toString(), + """ + fn main() -> void { + const answer = 42; + } + """); + + assertTrue(semanticTokens.legend().contains("pbs-keyword")); + assertTrue(semanticTokens.tokens().stream().anyMatch(token -> token.semanticKey().equals("pbs-keyword"))); + assertTrue(semanticTokens.tokens().stream().anyMatch(token -> token.semanticKey().equals("pbs-number"))); + } + private Path findRepoRoot(final Path start) { var current = start; while (current != null) { diff --git a/prometeu-lsp/prometeu-lsp-v1/src/test/java/p/studio/lsp/services/protocol/PrometeuLanguageServerTest.java b/prometeu-lsp/prometeu-lsp-v1/src/test/java/p/studio/lsp/services/protocol/PrometeuLanguageServerTest.java index 3f9dcb85..33ae0009 100644 --- a/prometeu-lsp/prometeu-lsp-v1/src/test/java/p/studio/lsp/services/protocol/PrometeuLanguageServerTest.java +++ b/prometeu-lsp/prometeu-lsp-v1/src/test/java/p/studio/lsp/services/protocol/PrometeuLanguageServerTest.java @@ -6,12 +6,14 @@ import org.eclipse.lsp4j.InitializeResult; import org.eclipse.lsp4j.InitializedParams; import org.eclipse.lsp4j.MessageParams; import org.eclipse.lsp4j.PublishDiagnosticsParams; +import org.eclipse.lsp4j.SemanticTokens; import org.eclipse.lsp4j.jsonrpc.ResponseErrorException; import org.eclipse.lsp4j.services.LanguageClient; import org.eclipse.lsp4j.services.TextDocumentService; import org.junit.jupiter.api.Test; import p.studio.lsp.messages.BaselineDocumentAnalysis; import p.studio.lsp.messages.BaselineHover; +import p.studio.lsp.messages.BaselineSemanticTokens; import p.studio.lsp.messages.BaselineServerDescription; import p.studio.lsp.messages.LspProjectContext; import p.studio.lsp.services.LanguageServiceBridge; @@ -77,7 +79,7 @@ class PrometeuLanguageServerTest { private static final class RecordingBridge implements LanguageServiceBridge { private int describeServerCalls; - private final BaselineServerDescription serverDescription = new BaselineServerDescription("demo", "1", true); + private final BaselineServerDescription serverDescription = new BaselineServerDescription("demo", "1", true, List.of()); @Override public BaselineServerDescription describeServer(final LspProjectContext project) { @@ -95,6 +97,11 @@ class PrometeuLanguageServerTest { return new BaselineHover("hover"); } + @Override + public BaselineSemanticTokens semanticTokens(final LspProjectContext context, final String documentUri, final String text) { + return new BaselineSemanticTokens(List.of(), List.of()); + } + @Override public String onSave(final LspProjectContext project, final String documentUri) { return "saved"; @@ -126,6 +133,11 @@ class PrometeuLanguageServerTest { throw new UnsupportedOperationException(); } + @Override + public SemanticTokens mapSemanticTokens(final BaselineSemanticTokens semanticTokens) { + throw new UnsupportedOperationException(); + } + @Override public MessageParams mapInfoMessage(final String message) { final MessageParams params = new MessageParams(); diff --git a/tools/vscode-extension/package.json b/tools/vscode-extension/package.json index 8621202e..159d05a2 100644 --- a/tools/vscode-extension/package.json +++ b/tools/vscode-extension/package.json @@ -52,6 +52,139 @@ "description": "Prometeu Studio LSP TCP port." } } + }, + "semanticTokenTypes": [ + { + "id": "pbs-comment", + "description": "PBS comment token" + }, + { + "id": "pbs-string", + "description": "PBS string token" + }, + { + "id": "pbs-number", + "description": "PBS number token" + }, + { + "id": "pbs-literal", + "description": "PBS literal token" + }, + { + "id": "pbs-lifecycle", + "description": "PBS lifecycle token" + }, + { + "id": "pbs-keyword", + "description": "PBS keyword token" + }, + { + "id": "pbs-operator", + "description": "PBS operator token" + }, + { + "id": "pbs-punctuation", + "description": "PBS punctuation token" + }, + { + "id": "pbs-function", + "description": "PBS function token" + }, + { + "id": "pbs-method", + "description": "PBS method token" + }, + { + "id": "pbs-constructor", + "description": "PBS constructor token" + }, + { + "id": "pbs-struct", + "description": "PBS struct token" + }, + { + "id": "pbs-contract", + "description": "PBS contract token" + }, + { + "id": "pbs-host", + "description": "PBS host token" + }, + { + "id": "pbs-builtin-type", + "description": "PBS builtin type token" + }, + { + "id": "pbs-service", + "description": "PBS service token" + }, + { + "id": "pbs-error", + "description": "PBS error token" + }, + { + "id": "pbs-enum", + "description": "PBS enum token" + }, + { + "id": "pbs-callback", + "description": "PBS callback token" + }, + { + "id": "pbs-global", + "description": "PBS global token" + }, + { + "id": "pbs-const", + "description": "PBS const token" + }, + { + "id": "pbs-implements", + "description": "PBS implements token" + }, + { + "id": "pbs-identifier", + "description": "PBS identifier token" + } + ], + "configurationDefaults": { + "editor.semanticHighlighting.enabled": true, + "[pbs]": { + "editor.semanticTokenColorCustomizations": { + "enabled": true, + "rules": { + "pbs-keyword": "#569cd6", + "pbs-lifecycle": "#ef50c0", + "pbs-function": "#f2c14e", + "pbs-method": "#f2c14e", + "pbs-constructor": "#ecdcaa", + "pbs-struct": "#4ec9b0", + "pbs-contract": "#78dce8", + "pbs-host": "#b7a2fa", + "pbs-builtin-type": "#8be9fd", + "pbs-service": "#b7a2fa", + "pbs-error": "#ff5b5b", + "pbs-enum": "#56cfe1", + "pbs-callback": "#b7a2fa", + "pbs-global": { + "foreground": "#f790fc", + "italic": true + }, + "pbs-const": "#f78c6c", + "pbs-implements": "#a1c181", + "pbs-string": "#00c088", + "pbs-number": "#ff90b0", + "pbs-comment": { + "foreground": "#c090b0", + "italic": true + }, + "pbs-literal": "#4fc1ff", + "pbs-operator": "#d4d4d4", + "pbs-punctuation": "#d4d4d4", + "pbs-identifier": "#d4d4d4" + } + } + } } }, "scripts": { -- 2.47.2 From baf9f90c93a8b8bf4d7d4a0e2569dbdd28d0ff85 Mon Sep 17 00:00:00 2001 From: bQUARKz Date: Wed, 6 May 2026 13:43:28 +0100 Subject: [PATCH 17/37] Frontend Visual Theme Spec and Retirement of Host-Consumed Semantic CSS --- discussion/index.ndjson | 3 +- ...nd-visual-theme-spec-and-css-retirement.md | 147 +++++++++++++++++ ...nd-visual-theme-spec-and-css-retirement.md | 152 ++++++++++++++++++ ...ntend-visual-contract-and-pbs-migration.md | 118 ++++++++++++++ ...sp-visual-theme-transport-and-selection.md | 114 +++++++++++++ ...visual-theme-adapter-and-css-retirement.md | 101 ++++++++++++ ...scode-dynamic-theme-translation-adapter.md | 100 ++++++++++++ tools/vscode-extension/package.json | 66 ++++---- 8 files changed, 766 insertions(+), 35 deletions(-) create mode 100644 discussion/workflow/agendas/AGD-0036-frontend-visual-theme-spec-and-css-retirement.md create mode 100644 discussion/workflow/decisions/DEC-0033-frontend-visual-theme-spec-and-css-retirement.md create mode 100644 discussion/workflow/plans/PLN-0068-frontend-visual-contract-and-pbs-migration.md create mode 100644 discussion/workflow/plans/PLN-0069-lsp-visual-theme-transport-and-selection.md create mode 100644 discussion/workflow/plans/PLN-0070-studio-visual-theme-adapter-and-css-retirement.md create mode 100644 discussion/workflow/plans/PLN-0071-vscode-dynamic-theme-translation-adapter.md diff --git a/discussion/index.ndjson b/discussion/index.ndjson index c862806e..9cf19490 100644 --- a/discussion/index.ndjson +++ b/discussion/index.ndjson @@ -1,4 +1,5 @@ -{"type":"meta","next_id":{"DSC":33,"AGD":36,"DEC":33,"PLN":68,"LSN":47,"CLSN":1}} +{"type":"meta","next_id":{"DSC":34,"AGD":37,"DEC":34,"PLN":72,"LSN":47,"CLSN":1}} +{"type":"discussion","id":"DSC-0033","status":"in_progress","ticket":"frontend-visual-theme-spec-and-css-retirement","title":"Frontend visual theme spec and retirement of host-consumed semantic CSS","created_at":"2026-05-06","updated_at":"2026-05-06","tags":["compiler","compiler-general","frontend","presentation","theming","studio","vscode","lsp","pbs"],"agendas":[{"id":"AGD-0036","file":"AGD-0036-frontend-visual-theme-spec-and-css-retirement.md","status":"accepted","created_at":"2026-05-06","updated_at":"2026-05-06"}],"decisions":[{"id":"DEC-0033","file":"DEC-0033-frontend-visual-theme-spec-and-css-retirement.md","status":"accepted","created_at":"2026-05-06","updated_at":"2026-05-06","ref_agenda":"AGD-0036"}],"plans":[{"id":"PLN-0068","file":"PLN-0068-frontend-visual-contract-and-pbs-migration.md","status":"open","created_at":"2026-05-06","updated_at":"2026-05-06","ref_decisions":["DEC-0033"]},{"id":"PLN-0069","file":"PLN-0069-lsp-visual-theme-transport-and-selection.md","status":"open","created_at":"2026-05-06","updated_at":"2026-05-06","ref_decisions":["DEC-0033"]},{"id":"PLN-0070","file":"PLN-0070-studio-visual-theme-adapter-and-css-retirement.md","status":"open","created_at":"2026-05-06","updated_at":"2026-05-06","ref_decisions":["DEC-0033"]},{"id":"PLN-0071","file":"PLN-0071-vscode-dynamic-theme-translation-adapter.md","status":"open","created_at":"2026-05-06","updated_at":"2026-05-06","ref_decisions":["DEC-0033"]}],"lessons":[]} {"type":"discussion","id":"DSC-0032","status":"in_progress","ticket":"studio-new-lsp-api-and-v1-boundary","title":"Novo boundary entre lsp-api, lsp-v1 e a extensao VS Code","created_at":"2026-05-05","updated_at":"2026-05-05","tags":["studio","lsp","vscode","protocol","api","boundary"],"agendas":[{"id":"AGD-0035","file":"AGD-0035-studio-new-lsp-api-and-v1-boundary.md","status":"accepted","created_at":"2026-05-05","updated_at":"2026-05-05"}],"decisions":[{"id":"DEC-0032","file":"DEC-0032-studio-new-lsp-api-and-v1-boundary.md","status":"accepted","created_at":"2026-05-05","updated_at":"2026-05-05","ref_agenda":"AGD-0035"}],"plans":[{"id":"PLN-0065","file":"PLN-0065-lsp-boundary-and-module-scaffolding.md","status":"done","created_at":"2026-05-05","updated_at":"2026-05-05","ref_decisions":["DEC-0032"]},{"id":"PLN-0066","file":"PLN-0066-project-scoped-lsp-server-lifecycle-in-studio.md","status":"done","created_at":"2026-05-05","updated_at":"2026-05-05","ref_decisions":["DEC-0032"]},{"id":"PLN-0067","file":"PLN-0067-compiler-backed-dumb-lsp-server-baseline.md","status":"done","created_at":"2026-05-05","updated_at":"2026-05-05","ref_decisions":["DEC-0032"]}],"lessons":[]} {"type":"discussion","id":"DSC-0031","status":"in_progress","ticket":"studio-editor-workspace-cleanup","title":"Limpeza completa do Workspace Editor do Studio e remoção dos acoplamentos legados","created_at":"2026-05-05","updated_at":"2026-05-05","tags":["studio","editor","cleanup","vfs","lsp","migration"],"agendas":[{"id":"AGD-0034","file":"AGD-0034-vscode-editor-migration-feasibility.md","status":"accepted","created_at":"2026-05-05","updated_at":"2026-05-05"}],"decisions":[{"id":"DEC-0031","file":"DEC-0031-studio-editor-workspace-cleanup.md","status":"in_progress","created_at":"2026-05-05","updated_at":"2026-05-05","ref_agenda":"AGD-0034"}],"plans":[{"id":"PLN-0062","file":"PLN-0062-shell-session-and-state-cleanup-after-editor-removal.md","status":"done","created_at":"2026-05-05","updated_at":"2026-05-05","ref_decisions":["DEC-0031"]},{"id":"PLN-0063","file":"PLN-0063-legacy-lsp-and-vfs-module-removal-with-runtime-preservation.md","status":"done","created_at":"2026-05-05","updated_at":"2026-05-05","ref_decisions":["DEC-0031"]},{"id":"PLN-0064","file":"PLN-0064-normative-test-and-lesson-cleanup-for-editor-stack-removal.md","status":"done","created_at":"2026-05-05","updated_at":"2026-05-05","ref_decisions":["DEC-0031"]}],"lessons":[]} {"type":"discussion","id":"DSC-0030","status":"done","ticket":"studio-scene-pack-runtime-binary-contract","title":"Studio scene pack contract for runtime SCENE binary payload","created_at":"2026-04-24","updated_at":"2026-05-01","tags":["studio","packer","runtime","scene","asset-pack","binary-format","tiled"],"agendas":[],"decisions":[],"plans":[],"lessons":[{"id":"LSN-0046","file":"discussion/lessons/DSC-0030-studio-scene-pack-runtime-binary-contract/LSN-0046-canonical-scene-owns-editorial-truth-while-pack-stays-request-driven.md","status":"done","created_at":"2026-05-01","updated_at":"2026-05-01"}]} diff --git a/discussion/workflow/agendas/AGD-0036-frontend-visual-theme-spec-and-css-retirement.md b/discussion/workflow/agendas/AGD-0036-frontend-visual-theme-spec-and-css-retirement.md new file mode 100644 index 00000000..ee9a3863 --- /dev/null +++ b/discussion/workflow/agendas/AGD-0036-frontend-visual-theme-spec-and-css-retirement.md @@ -0,0 +1,147 @@ +--- +id: AGD-0036 +ticket: frontend-visual-theme-spec-and-css-retirement +title: Frontend Visual Theme Spec and Retirement of Host-Consumed Semantic CSS +status: accepted +created: 2026-05-06 +resolved: 2026-05-06 +decision: DEC-0033 +tags: [compiler, compiler-general, frontend, presentation, theming, studio, vscode, lsp, pbs] +--- + +## Pain + +The current semantic highlighting path is no longer strong enough now that Prometeu must project frontend-owned presentation into more than one host. + +Today the frontend still effectively ships a host-facing CSS file as the practical source of truth for visual presentation. +That works tolerably for the legacy Studio editor path, but it collapses once the same frontend presentation must be exported to VS Code through LSP semantic tokens. + +The result is a weak cross-host contract: + +- the frontend publishes semantic keys, but not a complete visual spec, +- `semantic-highlighting.css` still acts as the real authored presentation artifact, +- VS Code only receives a partial hand-translated approximation, +- and each host risks drifting away from the frontend's intended visual identity. + +The CSS file should be treated as migration input only and must die by the end of this refactor. + +## Context + +Domain owner: `compiler/general` + +Propagation targets are expected in at least three places: + +- compiler frontend metadata and contracts, +- Studio host consumption, +- VS Code extension host consumption. + +Relevant historical context already exists in `LSN-0029`, which established frontend ownership of semantic presentation metadata through `FrontendSpec`. +That lesson is still useful for ownership boundaries, but it is not sufficient for the next wave because the current contract is too weak and too resource-oriented. + +Current state: + +- `FrontendSemanticPresentationSpec` exposes only `semanticKeys` and opaque `resources`, +- PBS publishes `/themes/pbs/semantic-highlighting.css` as a semantic presentation resource, +- Studio can consume that resource directly, +- VS Code cannot consume that CSS directly and must approximate it via `package.json` and semantic token theming, +- recent LSP work now transports PBS semantic token types, but the host-side rendering still falls short of the original PBS editor look. + +What is missing is a frontend-owned visual spec that is structured enough to be exported to multiple hosts without making CSS the canonical source. + +## Open Questions + +- [x] What is the canonical replacement for `semantic-highlighting.css` inside `FrontendSpec`? + R: a structured visual presentation spec (a JSON) that includes semantic token styles and editor-level colors. +- [x] Which parts of frontend presentation are normative and cross-host, and which are host-specific adapters only? + R: a ideia eh que o FE presentation possa ser completamente expostado para os clientes como o VSCode. +- [x] Should the visual contract be semantic-token-centric only, or should it also include editor-level colors such as base foreground, selection, gutter, and accent surfaces? + R: o contrato visual pode ofertar toda essa gama de atributos para cada token, o cliente (VSCode) pode usa-los para compor o tema, mas o contrato deve ser token-centric para garantir que a intenção visual seja sempre atrelada a chaves semânticas. +- [x] How should Studio consume the new visual spec without keeping CSS as a hidden canonical source? + R: o FE Presentation na medida que o servidor eh described oferece um contrato visual estruturado, o cliente (VSCode extension) deve consumir esse contrato e gerar o que tiver que gerar para compor o tema. Se o cliente usar CSS que gere isso. +- [x] How should VS Code consume the new visual spec: static generated contribution, runtime translation, or both? + R: A ideia eh que o cliente seja bem burro, ele deve ser uma maquina que traduz o contrato visual para um formato que o VSCode entenda, seja isso um contribution estatico ou uma tradução dinamica, o importante eh que o contrato visual seja o unico input e a fonte de verdade para a intencao visual do frontend. +- [x] How do we phase out existing frontend-owned CSS resources without breaking current Studio rendering during migration? + R: nada no studio depende desse CSS, ele eh um artefato de migração para o PBS. O contrato visual deve ser definido e implementado no PBS primeiro, usando o CSS como input para derivar o formato estruturado. Depois disso, o CSS pode ser descontinuado. +- [x] How do we version and validate the visual contract so new frontends can implement it consistently? + R: o contrato deve viver dentro de `FrontendSpec` e ser versionado junto com ele. + +## Options + +### Option A - Keep CSS as the canonical frontend artifact and add exporters around it + +- **Approach:** Preserve `semantic-highlighting.css` as the frontend-owned source and build tooling that parses or translates it into Studio and VS Code outputs. +- **Pro:** Smallest migration cost in the short term, because PBS already has authored CSS. +- **Con:** Keeps host-facing CSS as the source of truth, which is the wrong abstraction for multi-host consumption and weak for validation. +- **Maintainability:** Poor. Every new host would need a CSS interpretation path or a CSS-to-host adapter with lossy translation rules. + +### Option B - Introduce a structured frontend visual spec and treat CSS as a temporary migration input + +- **Approach:** Replace the current resource-centric semantic presentation contract with a structured visual spec published by the frontend. Use the existing CSS only as bootstrap input while migrating PBS, then retire it as canonical data. +- **Pro:** Creates a real multi-host contract that can be exported mechanically to Studio and VS Code while preserving frontend ownership. +- **Con:** Requires contract design, adapter work in both hosts, and a migration story for current frontend resources. +- **Maintainability:** Strong. New frontends would author one canonical visual contract and hosts would implement stable adapters. + +### Option C - Split the contract into semantic vocabulary plus host-owned themes + +- **Approach:** Keep frontend ownership only over semantic keys and let each host define its own visual theme for those keys. +- **Pro:** Simplifies frontend metadata and gives each host more freedom. +- **Con:** Reintroduces host ownership over frontend meaning in practice and guarantees visual drift between Studio and VS Code. +- **Maintainability:** Medium at best. It reduces frontend burden but loses the core requirement of frontend-owned identity. + +## Tradeoffs + +Option A looks attractive because it reuses existing assets, but it cements the wrong boundary. +If CSS remains canonical, the compiler/frontend layer still cannot describe its own presentation in a host-neutral way. + +Option C is cleaner than the current situation from a tooling perspective, but it fails the product goal. +The user experience would vary per host because visual meaning would no longer be frontend-owned. + +Option B is the only direction that preserves the previous ownership decision while extending it into a credible cross-host architecture. +Its cost is real, but that cost is exactly the work we need to make the contract durable. + +## Recommendation + +Adopt Option B. + +The frontend should publish a structured visual presentation spec as canonical data. +That spec should become the only normative source for frontend semantic/editor appearance that is intended to survive across hosts. + +`semantic-highlighting.css` should be used only as migration input for PBS while we derive the first structured visual spec. +After migration, CSS may remain as a generated Studio adapter artifact for a while, but it must no longer be treated as authored truth. + +The new contract likely needs at least these conceptual layers: + +- semantic token styles, +- editor surface colors, +- optional UI accent colors tied to the editing surface, +- explicit host adapter boundaries. + +The LSP path should transport structured visual data or enough structured metadata for the VS Code extension to render the same frontend-owned intent without reverse-engineering CSS. + +## Discussion + +This agenda is intentionally narrower than “general editor theming”. +The problem is not to invent a universal Prometeu theme engine first. +The problem is to stop using frontend-authored CSS as the canonical semantic/editor presentation contract and replace it with a frontend-owned visual spec that survives host translation. + +The most important discipline point is ownership: + +- compiler/frontend owns semantic and visual intent, +- LSP transports frontend-owned intent, +- Studio and VS Code are rendering adapters, +- host adapters may have capability gaps, but they must not become canonical. + +There is also an important migration constraint: + +- PBS is the first frontend and will define the initial shape, +- but the contract must not become “PBS-specific metadata with generic naming later”, +- instead it must be valid as a compiler-general surface that PBS implements first. + +## Resolution + +Accepted on 2026-05-06. + +The discussion resolves in favor of a structured frontend-owned visual theme specification with support for multiple themes per frontend. +Themes remain tied to the frontend's own semantic vocabulary. +Studio and the VS Code extension act as adapters over that contract. +`semantic-highlighting.css` remains migration input only and must be retired as canonical authored truth. diff --git a/discussion/workflow/decisions/DEC-0033-frontend-visual-theme-spec-and-css-retirement.md b/discussion/workflow/decisions/DEC-0033-frontend-visual-theme-spec-and-css-retirement.md new file mode 100644 index 00000000..77b9c876 --- /dev/null +++ b/discussion/workflow/decisions/DEC-0033-frontend-visual-theme-spec-and-css-retirement.md @@ -0,0 +1,152 @@ +--- +id: DEC-0033 +ticket: frontend-visual-theme-spec-and-css-retirement +title: Frontend-owned visual theme spec as canonical presentation contract +status: accepted +created: 2026-05-06 +accepted: 2026-05-06 +agenda: AGD-0036 +plans: [PLN-0068, PLN-0069, PLN-0070, PLN-0071] +tags: [compiler, compiler-general, frontend, presentation, theming, studio, vscode, lsp, pbs] +--- + +## Decision + +Prometeu SHALL replace frontend-authored host-consumed semantic CSS with a structured frontend-owned visual theme specification as the canonical presentation contract. + +This decision locks the following normative points: + +1. Each `FrontendSpec` MUST publish its own semantic vocabulary and MAY publish multiple visual themes for that vocabulary. +2. Visual themes MUST be frontend-owned and MUST remain associated with the semantic tokens defined by that same frontend. +3. `semantic-highlighting.css` MUST be treated as migration input only and MUST cease to be an authored canonical contract by the end of this refactor. +4. Studio and the VS Code extension MUST act as rendering adapters over the frontend-owned visual contract and MUST NOT become owners of frontend theme data. +5. The VS Code extension MUST translate the frontend visual contract dynamically or mechanically from the contract itself, so frontend visual adjustments do not require extension maintenance for each theme change. + +## Rationale + +The current model is structurally weak for multi-host consumption. +PBS still carries a CSS resource that works as the practical source of visual truth, while VS Code can only consume a partial manual approximation through semantic token configuration. + +That creates the wrong ownership boundary: + +1. the frontend owns semantic meaning but does not fully own its exported visual contract; +2. hosts are forced to reinterpret or approximate visual intent; +3. every frontend visual adjustment risks requiring host edits; +4. visual drift becomes likely across Studio and VS Code. + +The repository already established that semantic presentation belongs to the frontend. +This decision extends that ownership model into a stronger cross-host contract: + +1. the frontend authors semantic and visual intent once; +2. LSP transports that intent; +3. hosts adapt it without redefining it. + +## Technical Specification + +### 1. Canonical Visual Contract + +`FrontendSpec` MUST evolve to expose a structured visual presentation contract as canonical data. + +That contract MUST: + +1. live with the frontend definition; +2. be versioned together with `FrontendSpec`; +3. be sufficient for multiple hosts to render the frontend's intended appearance without interpreting CSS as the source of truth; +4. remain compiler-general even if PBS is the first frontend to implement it. + +The canonical contract MAY be encoded as JSON-backed structured data or as an equivalent strongly-typed model, but the authored source of truth MUST be the structured visual contract, not CSS. + +### 2. Frontend-Owned Themes + +Each frontend MAY publish multiple visual themes. + +Rules: + +1. themes MUST belong to the frontend that defines the semantic vocabulary they style; +2. themes MUST be expressed in terms of that frontend's own semantic token keys and related editor presentation surfaces; +3. hosts MAY select which frontend theme is active; +4. hosts MUST NOT redefine the theme contract as host-owned authored data. + +This means theme ownership is: + +1. frontend authors themes, +2. host selects and applies themes, +3. host does not author the frontend visual semantics. + +### 3. Token-Centric Contract with Editor Surfaces + +The visual contract MUST be token-centric, but it SHALL also support editor-level presentation data where needed to preserve frontend visual intent. + +Therefore the contract MUST be able to express: + +1. token-scoped presentation such as foreground, emphasis, and related token styling attributes; +2. editor surface colors such as base foreground, selection, gutter, and other editing-surface colors when they are part of frontend visual intent; +3. optional frontend-specific accents tied to the editing experience. + +Token-centricity remains mandatory because semantic meaning MUST stay anchored to semantic keys. +Editor-surface data is allowed because semantic fidelity alone is insufficient to reproduce frontend identity across hosts. + +### 4. Host Adapter Responsibilities + +Studio and the VS Code extension MUST consume the frontend visual contract as adapters. + +Studio: + +1. MUST consume the structured frontend visual contract; +2. MAY render through generated CSS or another host mechanism; +3. MUST NOT treat generated CSS as the canonical frontend artifact. + +VS Code extension: + +1. MUST consume the frontend visual contract through the server description path or an equivalent frontend-owned transport surface; +2. MUST translate that contract into whatever VS Code requires, whether through runtime translation, generated contributions, or another adapter mechanism; +3. MUST behave as a mechanical translator of the frontend contract; +4. MUST NOT require hand-maintained extension theme edits whenever a frontend changes a color, emphasis rule, or theme variant. + +### 5. LSP Transport Responsibilities + +The LSP path MUST transport enough structured frontend-owned visual information for hosts to render the active frontend theme. + +It MUST preserve: + +1. frontend identity, +2. semantic token identity, +3. theme identity where multiple themes exist, +4. visual attributes needed by the host adapter. + +LSP MUST NOT collapse frontend themes into host-authored generic theme categories. + +### 6. Migration and CSS Retirement + +`semantic-highlighting.css` is allowed only as migration input for the first structured contract derivation. + +Migration rules: + +1. PBS SHALL be the first frontend migrated; +2. the existing PBS CSS MAY be parsed or manually transcribed into the first canonical structured visual contract; +3. once the structured contract becomes authoritative, the CSS MUST no longer be treated as authored truth; +4. any remaining CSS after migration MAY exist only as generated adapter output or as temporary compatibility residue scheduled for removal; +5. the refactor is not complete while host-consumed semantic CSS remains the canonical frontend presentation source. + +### 7. Extension Stability Requirement + +This decision explicitly locks an operational requirement for `tools/vscode-extension`: + +1. frontend visual changes MUST be expressible by changing frontend-owned contract data; +2. such frontend changes MUST NOT force routine extension source edits; +3. the extension SHALL be stable as a contract adapter rather than a repository of manually curated frontend theme rules. + +## Constraints + +1. The canonical source of frontend visual intent MUST move out of authored CSS. +2. Theme ownership MUST remain with the frontend. +3. The contract MUST support multiple themes per frontend. +4. The contract MUST remain compiler-general and MUST NOT hardcode PBS as the universal model. +5. Hosts MUST remain adapters and MUST NOT become fallback authors of frontend visual identity. +6. Any derived plan MUST include an explicit migration path for PBS and explicit retirement of `semantic-highlighting.css` as canonical data. +7. Any derived plan MUST cover compiler contract changes, transport propagation, Studio consumption, and VS Code consumption. + +## Revision Log + +- 2026-05-06: Initial accepted decision from AGD-0036. +- 2026-05-06: Decomposed into PLN-0068, PLN-0069, PLN-0070, and PLN-0071. diff --git a/discussion/workflow/plans/PLN-0068-frontend-visual-contract-and-pbs-migration.md b/discussion/workflow/plans/PLN-0068-frontend-visual-contract-and-pbs-migration.md new file mode 100644 index 00000000..2a445745 --- /dev/null +++ b/discussion/workflow/plans/PLN-0068-frontend-visual-contract-and-pbs-migration.md @@ -0,0 +1,118 @@ +--- +id: PLN-0068 +ticket: frontend-visual-theme-spec-and-css-retirement +title: Frontend Visual Contract and PBS Migration +status: open +created: 2026-05-06 +completed: +tags: [compiler, compiler-general, frontend, pbs, presentation, theming, contract] +--- + +## Objective + +Introduce the canonical structured frontend visual contract in `FrontendSpec`, migrate PBS to that contract, and demote `semantic-highlighting.css` from authored truth to migration-only input. + +## Background + +`DEC-0033` locks that frontend visual intent must become structured canonical data, support multiple themes per frontend, remain token-centric, and retire authored host-consumed semantic CSS as the canonical source. + +PBS is the first frontend and therefore defines the first concrete migration path, but the contract MUST remain compiler-general rather than PBS-shaped by accident. + +## Scope + +### Included +- Evolve compiler/frontend metadata to publish a structured visual contract. +- Define the contract shape for semantic-token styling, editor surfaces, and theme identity. +- Migrate PBS to the new contract. +- Preserve any temporary migration utility needed to derive the first contract from the existing PBS CSS. +- Add validation tests that make the new contract normative and stable. + +### Excluded +- LSP transport changes. +- Studio rendering changes. +- VS Code runtime translation changes. + +## Non-Goals + +- Designing a generic host-owned theme engine. +- Supporting every possible frontend visual attribute in wave 1. +- Keeping authored CSS as a parallel canonical source. + +## Execution Steps + +### Step 1 - Define the structured visual contract in compiler-general surfaces + +**What:** Replace the resource-centric semantic presentation shape with a canonical structured visual contract in `FrontendSpec`. +**How:** Add or evolve frontend metadata models so each frontend can publish: + +1. semantic token vocabulary ownership, +2. one or more named visual themes, +3. token-centric visual rules, +4. editor-surface colors needed to preserve frontend identity. + +The model MUST be compiler-general and MUST NOT encode PBS-specific assumptions into the shared type system. +**File(s):** `prometeu-compiler/prometeu-compiler-core/src/main/java/p/studio/compiler/models/**`, affected frontend registry/definition surfaces. + +### Step 2 - Define the theme and token rule semantics explicitly + +**What:** Make the contract operational rather than descriptive. +**How:** Specify exact fields, invariants, and null/empty behavior for: + +1. theme identity, +2. theme selection metadata if needed at the contract layer, +3. token style rules, +4. editor surface colors, +5. versioning semantics inside or alongside `FrontendSpec`. + +The implementation MUST make it possible for hosts to translate the contract mechanically without inferring missing meaning. +**File(s):** `prometeu-compiler/prometeu-compiler-core/src/main/java/**`, associated tests in compiler modules. + +### Step 3 - Migrate PBS from authored CSS truth to structured contract truth + +**What:** Make PBS the first frontend to author the new contract. +**How:** Update `PBSDefinitions` and related PBS presentation metadata to publish one or more frontend-owned themes through the new contract. The existing `semantic-highlighting.css` MAY be parsed or manually transcribed to bootstrap the migration, but once the structured contract is in place, CSS MUST no longer be treated as authored truth. +**File(s):** `prometeu-compiler/frontends/prometeu-frontend-pbs/src/main/java/**`, `prometeu-compiler/frontends/prometeu-frontend-pbs/src/main/resources/themes/pbs/**`, related PBS tests. + +### Step 4 - Lock contract validity with tests + +**What:** Prevent future drift back to opaque resource ownership. +**How:** Add tests that assert: + +1. frontends publish structured visual themes, +2. PBS token vocabulary and theme definitions are coherent, +3. required token styles and editor-surface data resolve correctly, +4. authored CSS is no longer the canonical contract source. + +**File(s):** compiler-general and PBS test suites. + +## Test Requirements + +### Unit Tests +- Validate model invariants for theme IDs, token rules, and editor-surface fields. +- Validate `FrontendSpec` copies and exposes structured theme data safely. +- Validate PBS publishes at least one coherent theme using the new contract. + +### Integration Tests +- Run targeted compiler and PBS tests proving the contract compiles, resolves, and remains discoverable through frontend definitions. + +### Manual Verification +- Inspect the PBS frontend definition and confirm the structured contract is the readable authored source of truth. +- Confirm any remaining CSS is clearly migration-only or generated-output-only. + +## Acceptance Criteria + +- [ ] `FrontendSpec` publishes a structured canonical visual contract. +- [ ] The contract supports multiple themes per frontend. +- [ ] The contract is token-centric and can also express editor-surface colors. +- [ ] PBS is migrated to the new contract. +- [ ] `semantic-highlighting.css` is no longer treated as authored canonical frontend presentation data. + +## Dependencies + +- `DEC-0033` accepted and normatively locked. + +## Risks + +- Overfitting the first contract to PBS would weaken future frontend adoption. +- An underspecified token-style model would force host inference and violate the decision. +- Keeping CSS alive as a silent parallel truth source would nullify the migration. diff --git a/discussion/workflow/plans/PLN-0069-lsp-visual-theme-transport-and-selection.md b/discussion/workflow/plans/PLN-0069-lsp-visual-theme-transport-and-selection.md new file mode 100644 index 00000000..abd4f549 --- /dev/null +++ b/discussion/workflow/plans/PLN-0069-lsp-visual-theme-transport-and-selection.md @@ -0,0 +1,114 @@ +--- +id: PLN-0069 +ticket: frontend-visual-theme-spec-and-css-retirement +title: LSP Visual Theme Transport and Theme Selection Propagation +status: open +created: 2026-05-06 +completed: +tags: [studio, lsp, protocol, transport, presentation, theming, compiler] +--- + +## Objective + +Extend the LSP boundary and transport surfaces so hosts receive frontend-owned visual theme data, theme identity, and active-theme information without collapsing that contract into host-authored categories. + +## Background + +`DEC-0033` requires LSP to transport enough structured frontend-owned visual information for hosts to render the active frontend theme, preserve frontend and token identity, and avoid forcing the extension to keep hand-maintained theme rules. + +The compiler contract itself is handled by `PLN-0068`. This plan covers the transport boundary that carries that contract into host adapters. + +## Scope + +### Included +- Extend internal LSP-facing description or capability surfaces to expose structured frontend visual contract data. +- Transport theme identity and active-theme information where needed. +- Preserve semantic token identity and frontend ownership through mapping layers. +- Add transport-level tests for the new visual contract payloads. + +### Excluded +- Defining the compiler-general contract itself. +- Studio-side rendering implementation. +- VS Code-side rendering implementation. + +## Non-Goals + +- Inventing host-owned fallback theme categories. +- Expanding LSP beyond what is required to carry the visual contract. +- Building transport that requires hand-curated per-frontend extension updates. + +## Execution Steps + +### Step 1 - Extend internal LSP descriptions to carry visual contract data + +**What:** Evolve the LSP-side server/bridge description surfaces to expose frontend-owned visual contract data instead of ad hoc token metadata only. +**How:** Update `lsp-api` and `lsp-v1` internal description models so they can carry: + +1. frontend identity, +2. semantic token legend identity, +3. available theme definitions or references, +4. active theme selection. + +The payload shape MUST remain faithful to the frontend contract and MUST NOT normalize it into host-owned abstractions. +**File(s):** `prometeu-lsp/prometeu-lsp-api/src/main/java/**`, `prometeu-lsp/prometeu-lsp-v1/src/main/java/**`. + +### Step 2 - Thread the visual contract through bridge and mapper layers + +**What:** Ensure the compiler-backed bridge and protocol mappers preserve visual theme data end to end. +**How:** Update bridge services, protocol mappers, server description responses, and any capability/bootstrap path that currently exposes token data so they now expose the structured visual contract and active theme metadata. +**File(s):** `prometeu-lsp/prometeu-lsp-v1/src/main/java/p/studio/lsp/services/**`, `.../messages/**`, `.../mapping/**`. + +### Step 3 - Define theme selection behavior for host consumption + +**What:** Make active-theme semantics operational. +**How:** Define and implement the transport rule for which theme a host should apply: + +1. single-theme frontend behavior, +2. multi-theme frontend behavior, +3. default theme behavior when no host override is in play, +4. how active-theme selection is surfaced to adapters. + +The transport MUST make host behavior deterministic without host-owned guessing. +**File(s):** `prometeu-lsp/prometeu-lsp-api/**`, `prometeu-lsp/prometeu-lsp-v1/**`, tests. + +### Step 4 - Add transport conformance tests + +**What:** Prevent regression back to token-only or host-shaped payloads. +**How:** Add tests that verify: + +1. theme payloads are present, +2. token identities survive transport unchanged, +3. active-theme information is deterministic, +4. no mapper collapses frontend-owned visual data into host-authored categories. + +**File(s):** `prometeu-lsp/prometeu-lsp-v1/src/test/java/**`, `prometeu-lsp/prometeu-lsp-api/src/test/java/**` if needed. + +## Test Requirements + +### Unit Tests +- Validate DTO/model invariants for theme payloads and active-theme fields. +- Validate mapper behavior for full visual contract transport. + +### Integration Tests +- Run targeted LSP tests proving a compiler-backed frontend description reaches the host adapter layer with visual theme data intact. + +### Manual Verification +- Inspect initialize/description pathways and confirm theme metadata is present and frontend-shaped. + +## Acceptance Criteria + +- [ ] LSP description/transport surfaces carry structured frontend visual theme data. +- [ ] Theme identity and active-theme semantics are deterministic. +- [ ] Semantic token identity remains frontend-owned end to end. +- [ ] No LSP layer introduces host-owned theme abstractions as canonical transport data. + +## Dependencies + +- `DEC-0033` accepted and normatively locked. +- `PLN-0068` for the compiler-side contract shape and PBS migration. + +## Risks + +- Transporting too little theme data would force host inference and violate the decision. +- Transporting host-shaped payloads would silently recreate the wrong ownership boundary. +- Theme selection semantics can become ambiguous unless explicitly defined in this plan. diff --git a/discussion/workflow/plans/PLN-0070-studio-visual-theme-adapter-and-css-retirement.md b/discussion/workflow/plans/PLN-0070-studio-visual-theme-adapter-and-css-retirement.md new file mode 100644 index 00000000..34ff0106 --- /dev/null +++ b/discussion/workflow/plans/PLN-0070-studio-visual-theme-adapter-and-css-retirement.md @@ -0,0 +1,101 @@ +--- +id: PLN-0070 +ticket: frontend-visual-theme-spec-and-css-retirement +title: Studio Visual Theme Adapter and CSS Retirement +status: open +created: 2026-05-06 +completed: +tags: [studio, editor, presentation, theming, adapter, css-retirement] +--- + +## Objective + +Make Studio consume the structured frontend visual contract as an adapter, remove any remaining dependency on authored frontend semantic CSS as the canonical source, and keep any host rendering mechanism clearly derivative. + +## Background + +`DEC-0033` locks that Studio is a rendering adapter over frontend-owned visual themes and that generated CSS is acceptable only as an adapter mechanism, not as the canonical frontend artifact. + +This plan applies that rule to the Studio side of the stack. + +## Scope + +### Included +- Update Studio-side presentation registries or rendering services to consume structured frontend visual contract data. +- Generate or map host rendering artifacts from the structured contract if Studio still needs CSS or equivalent host render descriptors. +- Remove reliance on authored frontend semantic CSS as a direct semantic presentation contract. +- Add Studio tests proving the adapter path is derivative and deterministic. + +### Excluded +- Compiler-side contract design. +- LSP transport contract design. +- VS Code adapter behavior. + +## Non-Goals + +- Rebuilding the deleted legacy Studio editor stack. +- Introducing Studio-owned frontend themes. +- Preserving authored semantic CSS as a parallel truth source. + +## Execution Steps + +### Step 1 - Update Studio presentation consumption to use the structured contract + +**What:** Make Studio consume frontend-owned visual theme data instead of resource-only semantic presentation. +**How:** Update presentation registries, semantic highlighting services, or other editor-related rendering seams so they resolve structured visual theme data from the frontend description path. +**File(s):** `prometeu-studio/src/main/java/**`, any remaining editor/presentation adapter surfaces still active after cleanup. + +### Step 2 - Derive host rendering artifacts from the contract + +**What:** Keep Studio rendering mechanical. +**How:** If Studio still requires CSS or CSS-like structures, generate or map them from the structured frontend visual contract. The host-generated artifact MUST be clearly derivative and MUST NOT be treated as authored frontend truth. +**File(s):** `prometeu-studio/src/main/java/**`, possible theme/presentation helper modules, generated resource paths if adopted. + +### Step 3 - Remove direct canonical dependence on frontend semantic CSS + +**What:** Retire the old consumption model. +**How:** Remove or rewrite any code path that treats frontend semantic CSS resources as the canonical semantic presentation input. Leave only temporary compatibility or generated-output behavior if strictly needed during rollout. +**File(s):** `prometeu-studio/**`, related frontend resource loading code. + +### Step 4 - Add Studio adapter conformance tests + +**What:** Lock the adapter boundary. +**How:** Add tests that verify: + +1. Studio consumes structured frontend visual themes, +2. token style rendering inputs are contract-derived, +3. any generated CSS is derivative, +4. Studio does not silently fall back to host-authored frontend theme logic. + +**File(s):** `prometeu-studio/src/test/java/**` and any relevant integration test modules. + +## Test Requirements + +### Unit Tests +- Validate contract-to-rendering translation logic. +- Validate theme selection consumption on the Studio side. + +### Integration Tests +- Run targeted Studio-side tests proving frontend presentation resolves from structured contract data and not from authored semantic CSS. + +### Manual Verification +- Inspect the Studio path and confirm remaining CSS, if any, is generated or compatibility-only. + +## Acceptance Criteria + +- [ ] Studio consumes structured frontend visual contract data. +- [ ] Any Studio-side CSS or equivalent rendering descriptor is derivative, not canonical. +- [ ] Direct canonical dependence on authored frontend semantic CSS is removed. +- [ ] Studio does not reauthor frontend visual identity locally. + +## Dependencies + +- `DEC-0033` accepted and normatively locked. +- `PLN-0068` for the canonical compiler/frontend contract. +- `PLN-0069` for transport of visual contract data into the host boundary. + +## Risks + +- Studio may still hide old CSS assumptions in helper layers unless the migration is exhaustive. +- Generated CSS can accidentally become the new silent truth source if ownership boundaries are not explicit in code and tests. +- Residual editor cleanup from earlier refactors may obscure the remaining active consumption path. diff --git a/discussion/workflow/plans/PLN-0071-vscode-dynamic-theme-translation-adapter.md b/discussion/workflow/plans/PLN-0071-vscode-dynamic-theme-translation-adapter.md new file mode 100644 index 00000000..a7cdbf4c --- /dev/null +++ b/discussion/workflow/plans/PLN-0071-vscode-dynamic-theme-translation-adapter.md @@ -0,0 +1,100 @@ +--- +id: PLN-0071 +ticket: frontend-visual-theme-spec-and-css-retirement +title: VS Code Dynamic Theme Translation Adapter +status: open +created: 2026-05-06 +completed: +tags: [vscode, extension, lsp, presentation, theming, adapter] +--- + +## Objective + +Turn the VS Code extension into a stable adapter that translates frontend-owned visual theme contracts into VS Code-compatible rendering behavior without requiring source edits for routine frontend theme changes. + +## Background + +`DEC-0033` explicitly locks that the extension must not become a repository of manually curated frontend theme rules. The extension must translate the contract it receives rather than being edited whenever a frontend changes colors, emphasis, or theme variants. + +This plan covers the client-side adapter behavior that satisfies that requirement. + +## Scope + +### Included +- Replace hardcoded per-frontend visual theme rules with dynamic or generated translation based on the transported frontend contract. +- Define the minimum static VS Code contribution surface still required by the platform. +- Support multi-theme frontend data consumption and active-theme application. +- Add extension tests or verification coverage around theme translation. + +### Excluded +- Compiler-side contract definition. +- LSP transport definition. +- Studio rendering behavior. + +## Non-Goals + +- Building a general-purpose VS Code theme marketplace artifact. +- Allowing the extension to become a second authored source of frontend theme truth. +- Solving unrelated reconnect or transport lifecycle issues beyond what this adapter needs. + +## Execution Steps + +### Step 1 - Identify the minimal static VS Code contribution surface + +**What:** Separate what the extension must declare statically from what it can translate dynamically. +**How:** Keep only the minimal `package.json` contribution data required for VS Code to recognize semantic token kinds or activate the extension. Remove hardcoded frontend-specific color rules from static configuration where dynamic translation can take over. +**File(s):** `tools/vscode-extension/package.json`, related extension bootstrap files. + +### Step 2 - Implement contract-to-VS Code theme translation + +**What:** Translate frontend-owned visual contract data into VS Code-understandable configuration. +**How:** Update extension runtime code to receive the transported visual theme contract, map token and editor-surface data into the VS Code APIs/configuration model, and apply the active frontend theme deterministically. +**File(s):** `tools/vscode-extension/src/**`, mirrored build outputs only if local toolchain constraints require temporary manual sync. + +### Step 3 - Support multi-theme frontends without extension source edits + +**What:** Make frontend theme growth operationally cheap. +**How:** Ensure that adding or changing frontend-owned themes does not require new extension source logic unless the VS Code platform itself introduces a new capability boundary. Theme identity, token rules, and active selection must be data-driven. +**File(s):** `tools/vscode-extension/src/**`, possible supporting protocol model surfaces if consumed directly. + +### Step 4 - Add adapter verification coverage + +**What:** Protect the no-manual-theme-maintenance rule. +**How:** Add tests or deterministic verification around: + +1. translation of token rules, +2. translation of editor-surface colors where supported, +3. handling of multiple frontend themes, +4. absence of hardcoded PBS-only theme logic in the adapter path. + +**File(s):** `tools/vscode-extension/src/test/**` if present, or equivalent test harness/verification approach adopted by the extension module. + +## Test Requirements + +### Unit Tests +- Validate translation of structured token rules into VS Code-compatible theme rules. +- Validate active-theme switching behavior for data-driven frontend themes. + +### Integration Tests +- Run extension-targeted validation proving the frontend contract can change without source-level theme edits. + +### Manual Verification +- Open PBS content through the extension and confirm the active theme is applied from transported contract data rather than hardcoded `package.json` color tables. + +## Acceptance Criteria + +- [ ] The extension no longer depends on hardcoded frontend-specific theme rules as the primary rendering source. +- [ ] Frontend theme changes are driven by contract data rather than extension source edits. +- [ ] Multi-theme frontend payloads can be translated and applied deterministically. +- [ ] The remaining static VS Code contribution surface is minimal and structural only. + +## Dependencies + +- `DEC-0033` accepted and normatively locked. +- `PLN-0069` for transport of visual theme data to the extension. + +## Risks + +- VS Code platform constraints may force a hybrid static/runtime model that must stay carefully bounded. +- The current local Node/TypeScript environment issues can slow validation. +- Leaving too much theme data in `package.json` would preserve the current maintenance problem under a new name. diff --git a/tools/vscode-extension/package.json b/tools/vscode-extension/package.json index 159d05a2..425b945d 100644 --- a/tools/vscode-extension/package.json +++ b/tools/vscode-extension/package.json @@ -149,40 +149,38 @@ ], "configurationDefaults": { "editor.semanticHighlighting.enabled": true, - "[pbs]": { - "editor.semanticTokenColorCustomizations": { - "enabled": true, - "rules": { - "pbs-keyword": "#569cd6", - "pbs-lifecycle": "#ef50c0", - "pbs-function": "#f2c14e", - "pbs-method": "#f2c14e", - "pbs-constructor": "#ecdcaa", - "pbs-struct": "#4ec9b0", - "pbs-contract": "#78dce8", - "pbs-host": "#b7a2fa", - "pbs-builtin-type": "#8be9fd", - "pbs-service": "#b7a2fa", - "pbs-error": "#ff5b5b", - "pbs-enum": "#56cfe1", - "pbs-callback": "#b7a2fa", - "pbs-global": { - "foreground": "#f790fc", - "italic": true - }, - "pbs-const": "#f78c6c", - "pbs-implements": "#a1c181", - "pbs-string": "#00c088", - "pbs-number": "#ff90b0", - "pbs-comment": { - "foreground": "#c090b0", - "italic": true - }, - "pbs-literal": "#4fc1ff", - "pbs-operator": "#d4d4d4", - "pbs-punctuation": "#d4d4d4", - "pbs-identifier": "#d4d4d4" - } + "editor.semanticTokenColorCustomizations": { + "enabled": true, + "rules": { + "pbs-keyword:pbs": "#569cd6", + "pbs-lifecycle:pbs": "#ef50c0", + "pbs-function:pbs": "#f2c14e", + "pbs-method:pbs": "#f2c14e", + "pbs-constructor:pbs": "#ecdcaa", + "pbs-struct:pbs": "#4ec9b0", + "pbs-contract:pbs": "#78dce8", + "pbs-host:pbs": "#b7a2fa", + "pbs-builtin-type:pbs": "#8be9fd", + "pbs-service:pbs": "#b7a2fa", + "pbs-error:pbs": "#ff5b5b", + "pbs-enum:pbs": "#56cfe1", + "pbs-callback:pbs": "#b7a2fa", + "pbs-global:pbs": { + "foreground": "#f790fc", + "italic": true + }, + "pbs-const:pbs": "#f78c6c", + "pbs-implements:pbs": "#a1c181", + "pbs-string:pbs": "#00c088", + "pbs-number:pbs": "#ff90b0", + "pbs-comment:pbs": { + "foreground": "#c090b0", + "italic": true + }, + "pbs-literal:pbs": "#4fc1ff", + "pbs-operator:pbs": "#d4d4d4", + "pbs-punctuation:pbs": "#d4d4d4", + "pbs-identifier:pbs": "#d4d4d4" } } } -- 2.47.2 From 54f8c0d6d828e9905bc0a7ab1ecb5d573cd2bf08 Mon Sep 17 00:00:00 2001 From: bQUARKz Date: Wed, 6 May 2026 13:46:23 +0100 Subject: [PATCH 18/37] implements PLN-0068 --- .../p/studio/compiler/PBSDefinitions.java | 40 +++++++++++++++- .../PbsSemanticPresentationContractTest.java | 22 +++++---- .../models/FrontendEditorPaletteSpec.java | 33 +++++++++++++ .../FrontendSemanticPresentationSpec.java | 45 ++++++++++++++++-- .../models/FrontendTokenStyleSpec.java | 26 ++++++++++ .../models/FrontendVisualThemeSpec.java | 47 +++++++++++++++++++ 6 files changed, 199 insertions(+), 14 deletions(-) create mode 100644 prometeu-compiler/prometeu-compiler-core/src/main/java/p/studio/compiler/models/FrontendEditorPaletteSpec.java create mode 100644 prometeu-compiler/prometeu-compiler-core/src/main/java/p/studio/compiler/models/FrontendTokenStyleSpec.java create mode 100644 prometeu-compiler/prometeu-compiler-core/src/main/java/p/studio/compiler/models/FrontendVisualThemeSpec.java diff --git a/prometeu-compiler/frontends/prometeu-frontend-pbs/src/main/java/p/studio/compiler/PBSDefinitions.java b/prometeu-compiler/frontends/prometeu-frontend-pbs/src/main/java/p/studio/compiler/PBSDefinitions.java index 27b9781c..28ea25d7 100644 --- a/prometeu-compiler/frontends/prometeu-frontend-pbs/src/main/java/p/studio/compiler/PBSDefinitions.java +++ b/prometeu-compiler/frontends/prometeu-frontend-pbs/src/main/java/p/studio/compiler/PBSDefinitions.java @@ -1,7 +1,10 @@ package p.studio.compiler; import p.studio.compiler.models.FrontendSpec; +import p.studio.compiler.models.FrontendEditorPaletteSpec; import p.studio.compiler.models.FrontendSemanticPresentationSpec; +import p.studio.compiler.models.FrontendTokenStyleSpec; +import p.studio.compiler.models.FrontendVisualThemeSpec; import p.studio.compiler.pbs.PbsSemanticKind; import p.studio.utilities.structures.ReadOnlySet; @@ -16,6 +19,41 @@ public class PBSDefinitions { .stdlibVersions(List.of(FrontendSpec.Stdlib.asDefault(1))) .semanticPresentation(new FrontendSemanticPresentationSpec( PbsSemanticKind.semanticKeys(), - List.of("/themes/pbs/semantic-highlighting.css"))) + List.of(new FrontendVisualThemeSpec( + "pbs-default", + "PBS Default", + new FrontendEditorPaletteSpec( + "#d9e2ec", + "#2d4f6b", + "#2d4f6b", + "#6f8193", + "#2c2140", + "#a47dff", + "#efe6ff"), + List.of( + new FrontendTokenStyleSpec("pbs-comment", "#c090b0", true, false, false), + new FrontendTokenStyleSpec("pbs-string", "#00c088", false, false, false), + new FrontendTokenStyleSpec("pbs-number", "#ff90b0", false, false, false), + new FrontendTokenStyleSpec("pbs-literal", "#4fc1ff", false, false, false), + new FrontendTokenStyleSpec("pbs-lifecycle", "#ef50c0", false, false, false), + new FrontendTokenStyleSpec("pbs-keyword", "#569cd6", false, false, false), + new FrontendTokenStyleSpec("pbs-operator", "#d4d4d4", false, false, false), + new FrontendTokenStyleSpec("pbs-punctuation", "#d4d4d4", false, false, false), + new FrontendTokenStyleSpec("pbs-function", "#f2c14e", false, false, false), + new FrontendTokenStyleSpec("pbs-method", "#f2c14e", false, false, false), + new FrontendTokenStyleSpec("pbs-constructor", "#ecdcaa", false, false, false), + new FrontendTokenStyleSpec("pbs-struct", "#4ec9b0", false, false, false), + new FrontendTokenStyleSpec("pbs-contract", "#78dce8", false, false, false), + new FrontendTokenStyleSpec("pbs-host", "#b7a2fa", false, false, false), + new FrontendTokenStyleSpec("pbs-builtin-type", "#8be9fd", false, false, false), + new FrontendTokenStyleSpec("pbs-service", "#b7a2fa", false, false, false), + new FrontendTokenStyleSpec("pbs-error", "#ff5b5b", false, false, false), + new FrontendTokenStyleSpec("pbs-enum", "#56cfe1", false, false, false), + new FrontendTokenStyleSpec("pbs-callback", "#b7a2fa", false, false, false), + new FrontendTokenStyleSpec("pbs-global", "#f790fc", true, false, false), + new FrontendTokenStyleSpec("pbs-const", "#f78c6c", false, false, false), + new FrontendTokenStyleSpec("pbs-implements", "#a1c181", false, false, false), + new FrontendTokenStyleSpec("pbs-identifier", "#d4d4d4", false, false, false)))), + "pbs-default")) .build(); } diff --git a/prometeu-compiler/frontends/prometeu-frontend-pbs/src/test/java/p/studio/compiler/pbs/PbsSemanticPresentationContractTest.java b/prometeu-compiler/frontends/prometeu-frontend-pbs/src/test/java/p/studio/compiler/pbs/PbsSemanticPresentationContractTest.java index 761a4cff..c78457c0 100644 --- a/prometeu-compiler/frontends/prometeu-frontend-pbs/src/test/java/p/studio/compiler/pbs/PbsSemanticPresentationContractTest.java +++ b/prometeu-compiler/frontends/prometeu-frontend-pbs/src/test/java/p/studio/compiler/pbs/PbsSemanticPresentationContractTest.java @@ -3,11 +3,8 @@ package p.studio.compiler.pbs; import org.junit.jupiter.api.Test; import p.studio.compiler.PBSDefinitions; -import java.net.URL; - import static org.junit.jupiter.api.Assertions.assertEquals; import static org.junit.jupiter.api.Assertions.assertFalse; -import static org.junit.jupiter.api.Assertions.assertNotNull; import static org.junit.jupiter.api.Assertions.assertTrue; final class PbsSemanticPresentationContractTest { @@ -18,16 +15,21 @@ final class PbsSemanticPresentationContractTest { assertFalse(presentation.semanticKeys().isEmpty()); assertEquals(PbsSemanticKind.semanticKeys(), presentation.semanticKeys()); - assertEquals(1, presentation.resources().size()); - assertEquals("/themes/pbs/semantic-highlighting.css", presentation.resources().getFirst()); + assertEquals("pbs-default", presentation.defaultThemeId()); + assertEquals(1, presentation.themes().size()); + assertEquals("PBS Default", presentation.defaultTheme().displayName()); + assertEquals("#d9e2ec", presentation.defaultTheme().editorPalette().baseForeground()); + assertEquals("#569cd6", presentation.defaultTheme().requireTokenStyle("pbs-keyword").foreground()); + assertTrue(presentation.defaultTheme().requireTokenStyle("pbs-comment").italic()); } @Test - void shouldPublishResolvableSemanticPresentationResources() { - final var resourcePath = PBSDefinitions.PBS.getSemanticPresentation().resources().getFirst(); - final URL resource = PBSDefinitions.class.getResource(resourcePath); + void shouldCoverTheWholePbsSemanticVocabularyInTheDefaultTheme() { + final var presentation = PBSDefinitions.PBS.getSemanticPresentation(); + final var defaultTheme = presentation.defaultTheme(); - assertNotNull(resource, resourcePath); - assertTrue(resource.toExternalForm().endsWith("themes/pbs/semantic-highlighting.css")); + assertEquals( + PbsSemanticKind.semanticKeys(), + defaultTheme.tokenStyles().stream().map(tokenStyle -> tokenStyle.semanticKey()).toList()); } } diff --git a/prometeu-compiler/prometeu-compiler-core/src/main/java/p/studio/compiler/models/FrontendEditorPaletteSpec.java b/prometeu-compiler/prometeu-compiler-core/src/main/java/p/studio/compiler/models/FrontendEditorPaletteSpec.java new file mode 100644 index 00000000..3cd2cfd0 --- /dev/null +++ b/prometeu-compiler/prometeu-compiler-core/src/main/java/p/studio/compiler/models/FrontendEditorPaletteSpec.java @@ -0,0 +1,33 @@ +package p.studio.compiler.models; + +import java.util.Objects; + +public record FrontendEditorPaletteSpec( + String baseForeground, + String selectionBackground, + String activeHighlightBackground, + String lineNumberForeground, + String statusChipBackground, + String statusChipBorder, + String statusChipForeground) { + + public FrontendEditorPaletteSpec { + baseForeground = requireColor(baseForeground, "baseForeground"); + selectionBackground = requireColor(selectionBackground, "selectionBackground"); + activeHighlightBackground = requireColor(activeHighlightBackground, "activeHighlightBackground"); + lineNumberForeground = requireColor(lineNumberForeground, "lineNumberForeground"); + statusChipBackground = requireColor(statusChipBackground, "statusChipBackground"); + statusChipBorder = requireColor(statusChipBorder, "statusChipBorder"); + statusChipForeground = requireColor(statusChipForeground, "statusChipForeground"); + } + + private static String requireColor( + final String value, + final String field) { + final String candidate = Objects.requireNonNull(value, field).trim(); + if (candidate.isEmpty()) { + throw new IllegalArgumentException(field + " must not be blank"); + } + return candidate; + } +} diff --git a/prometeu-compiler/prometeu-compiler-core/src/main/java/p/studio/compiler/models/FrontendSemanticPresentationSpec.java b/prometeu-compiler/prometeu-compiler-core/src/main/java/p/studio/compiler/models/FrontendSemanticPresentationSpec.java index 73691d86..989f5959 100644 --- a/prometeu-compiler/prometeu-compiler-core/src/main/java/p/studio/compiler/models/FrontendSemanticPresentationSpec.java +++ b/prometeu-compiler/prometeu-compiler-core/src/main/java/p/studio/compiler/models/FrontendSemanticPresentationSpec.java @@ -5,14 +5,53 @@ import java.util.Objects; public record FrontendSemanticPresentationSpec( List semanticKeys, - List resources) { + List themes, + String defaultThemeId) { public FrontendSemanticPresentationSpec { semanticKeys = List.copyOf(Objects.requireNonNull(semanticKeys, "semanticKeys")); - resources = List.copyOf(Objects.requireNonNull(resources, "resources")); + themes = List.copyOf(Objects.requireNonNull(themes, "themes")); + defaultThemeId = Objects.requireNonNull(defaultThemeId, "defaultThemeId").trim(); + if (semanticKeys.isEmpty() && themes.isEmpty()) { + if (!defaultThemeId.isEmpty()) { + throw new IllegalArgumentException("defaultThemeId must be blank when no themes are declared"); + } + } else { + defaultThemeId = requireText(defaultThemeId, "defaultThemeId"); + if (themes.isEmpty()) { + throw new IllegalArgumentException("themes must not be empty"); + } + if (themes.stream().map(FrontendVisualThemeSpec::themeId).noneMatch(defaultThemeId::equals)) { + throw new IllegalArgumentException("defaultThemeId must reference one of the declared themes"); + } + } } public static FrontendSemanticPresentationSpec empty() { - return new FrontendSemanticPresentationSpec(List.of(), List.of()); + return new FrontendSemanticPresentationSpec(List.of(), List.of(), ""); + } + + public FrontendVisualThemeSpec defaultTheme() { + if (themes.isEmpty()) { + throw new IllegalStateException("empty semantic presentation has no default theme"); + } + return themes.stream() + .filter(theme -> theme.themeId().equals(defaultThemeId)) + .findFirst() + .orElseThrow(() -> new IllegalStateException("defaultThemeId must resolve to a declared theme")); + } + + public boolean isEmpty() { + return semanticKeys.isEmpty() && themes.isEmpty() && defaultThemeId.isEmpty(); + } + + private static String requireText( + final String value, + final String field) { + final String candidate = Objects.requireNonNull(value, field).trim(); + if (candidate.isEmpty()) { + throw new IllegalArgumentException(field + " must not be blank"); + } + return candidate; } } diff --git a/prometeu-compiler/prometeu-compiler-core/src/main/java/p/studio/compiler/models/FrontendTokenStyleSpec.java b/prometeu-compiler/prometeu-compiler-core/src/main/java/p/studio/compiler/models/FrontendTokenStyleSpec.java new file mode 100644 index 00000000..5405017c --- /dev/null +++ b/prometeu-compiler/prometeu-compiler-core/src/main/java/p/studio/compiler/models/FrontendTokenStyleSpec.java @@ -0,0 +1,26 @@ +package p.studio.compiler.models; + +import java.util.Objects; + +public record FrontendTokenStyleSpec( + String semanticKey, + String foreground, + boolean italic, + boolean bold, + boolean underline) { + + public FrontendTokenStyleSpec { + semanticKey = requireText(semanticKey, "semanticKey"); + foreground = requireText(foreground, "foreground"); + } + + private static String requireText( + final String value, + final String field) { + final String candidate = Objects.requireNonNull(value, field).trim(); + if (candidate.isEmpty()) { + throw new IllegalArgumentException(field + " must not be blank"); + } + return candidate; + } +} diff --git a/prometeu-compiler/prometeu-compiler-core/src/main/java/p/studio/compiler/models/FrontendVisualThemeSpec.java b/prometeu-compiler/prometeu-compiler-core/src/main/java/p/studio/compiler/models/FrontendVisualThemeSpec.java new file mode 100644 index 00000000..cf8603c2 --- /dev/null +++ b/prometeu-compiler/prometeu-compiler-core/src/main/java/p/studio/compiler/models/FrontendVisualThemeSpec.java @@ -0,0 +1,47 @@ +package p.studio.compiler.models; + +import java.util.LinkedHashMap; +import java.util.List; +import java.util.Map; +import java.util.Objects; + +public record FrontendVisualThemeSpec( + String themeId, + String displayName, + FrontendEditorPaletteSpec editorPalette, + List tokenStyles) { + + public FrontendVisualThemeSpec { + themeId = requireText(themeId, "themeId"); + displayName = requireText(displayName, "displayName"); + editorPalette = Objects.requireNonNull(editorPalette, "editorPalette"); + tokenStyles = List.copyOf(Objects.requireNonNull(tokenStyles, "tokenStyles")); + if (tokenStyles.isEmpty()) { + throw new IllegalArgumentException("tokenStyles must not be empty"); + } + final Map bySemanticKey = new LinkedHashMap<>(); + for (final FrontendTokenStyleSpec tokenStyle : tokenStyles) { + final FrontendTokenStyleSpec previous = bySemanticKey.put(tokenStyle.semanticKey(), tokenStyle); + if (previous != null) { + throw new IllegalArgumentException("duplicate token style for semantic key: " + tokenStyle.semanticKey()); + } + } + } + + public FrontendTokenStyleSpec requireTokenStyle(final String semanticKey) { + return tokenStyles.stream() + .filter(tokenStyle -> tokenStyle.semanticKey().equals(semanticKey)) + .findFirst() + .orElseThrow(() -> new IllegalArgumentException("missing token style for semantic key: " + semanticKey)); + } + + private static String requireText( + final String value, + final String field) { + final String candidate = Objects.requireNonNull(value, field).trim(); + if (candidate.isEmpty()) { + throw new IllegalArgumentException(field + " must not be blank"); + } + return candidate; + } +} -- 2.47.2 From 41bcd8c52a3678da19fff3be48af4b49033308f9 Mon Sep 17 00:00:00 2001 From: bQUARKz Date: Wed, 6 May 2026 13:48:09 +0100 Subject: [PATCH 19/37] implements PLN-0069 --- .../lsp/messages/BaselineEditorPalette.java | 33 +++++++++++++++++ .../messages/BaselineServerDescription.java | 9 ++++- .../lsp/messages/BaselineTokenStyle.java | 26 ++++++++++++++ .../lsp/messages/BaselineVisualTheme.java | 31 ++++++++++++++++ .../CompilerLanguageServiceBridge.java | 35 ++++++++++++++++++- .../CompilerLanguageServiceBridgeTest.java | 16 +++++++++ .../protocol/PrometeuLanguageServerTest.java | 15 +++++++- 7 files changed, 162 insertions(+), 3 deletions(-) create mode 100644 prometeu-lsp/prometeu-lsp-v1/src/main/java/p/studio/lsp/messages/BaselineEditorPalette.java create mode 100644 prometeu-lsp/prometeu-lsp-v1/src/main/java/p/studio/lsp/messages/BaselineTokenStyle.java create mode 100644 prometeu-lsp/prometeu-lsp-v1/src/main/java/p/studio/lsp/messages/BaselineVisualTheme.java diff --git a/prometeu-lsp/prometeu-lsp-v1/src/main/java/p/studio/lsp/messages/BaselineEditorPalette.java b/prometeu-lsp/prometeu-lsp-v1/src/main/java/p/studio/lsp/messages/BaselineEditorPalette.java new file mode 100644 index 00000000..0e638149 --- /dev/null +++ b/prometeu-lsp/prometeu-lsp-v1/src/main/java/p/studio/lsp/messages/BaselineEditorPalette.java @@ -0,0 +1,33 @@ +package p.studio.lsp.messages; + +import java.util.Objects; + +public record BaselineEditorPalette( + String baseForeground, + String selectionBackground, + String activeHighlightBackground, + String lineNumberForeground, + String statusChipBackground, + String statusChipBorder, + String statusChipForeground) { + + public BaselineEditorPalette { + baseForeground = requireText(baseForeground, "baseForeground"); + selectionBackground = requireText(selectionBackground, "selectionBackground"); + activeHighlightBackground = requireText(activeHighlightBackground, "activeHighlightBackground"); + lineNumberForeground = requireText(lineNumberForeground, "lineNumberForeground"); + statusChipBackground = requireText(statusChipBackground, "statusChipBackground"); + statusChipBorder = requireText(statusChipBorder, "statusChipBorder"); + statusChipForeground = requireText(statusChipForeground, "statusChipForeground"); + } + + private static String requireText( + final String value, + final String field) { + final String candidate = Objects.requireNonNull(value, field).trim(); + if (candidate.isEmpty()) { + throw new IllegalArgumentException(field + " must not be blank"); + } + return candidate; + } +} diff --git a/prometeu-lsp/prometeu-lsp-v1/src/main/java/p/studio/lsp/messages/BaselineServerDescription.java b/prometeu-lsp/prometeu-lsp-v1/src/main/java/p/studio/lsp/messages/BaselineServerDescription.java index af31b775..daf47a62 100644 --- a/prometeu-lsp/prometeu-lsp-v1/src/main/java/p/studio/lsp/messages/BaselineServerDescription.java +++ b/prometeu-lsp/prometeu-lsp-v1/src/main/java/p/studio/lsp/messages/BaselineServerDescription.java @@ -7,12 +7,19 @@ public record BaselineServerDescription( String name, String version, boolean hoverSupported, - List semanticTokenTypes) { + List semanticTokenTypes, + List visualThemes, + String activeVisualThemeId) { public BaselineServerDescription { name = requireText(name, "name"); version = requireText(version, "version"); semanticTokenTypes = List.copyOf(Objects.requireNonNull(semanticTokenTypes, "semanticTokenTypes")); + visualThemes = List.copyOf(Objects.requireNonNull(visualThemes, "visualThemes")); + activeVisualThemeId = requireText(activeVisualThemeId, "activeVisualThemeId"); + if (visualThemes.stream().map(BaselineVisualTheme::themeId).noneMatch(activeVisualThemeId::equals)) { + throw new IllegalArgumentException("activeVisualThemeId must reference one of the declared visual themes"); + } } private static String requireText( diff --git a/prometeu-lsp/prometeu-lsp-v1/src/main/java/p/studio/lsp/messages/BaselineTokenStyle.java b/prometeu-lsp/prometeu-lsp-v1/src/main/java/p/studio/lsp/messages/BaselineTokenStyle.java new file mode 100644 index 00000000..7fbcaab1 --- /dev/null +++ b/prometeu-lsp/prometeu-lsp-v1/src/main/java/p/studio/lsp/messages/BaselineTokenStyle.java @@ -0,0 +1,26 @@ +package p.studio.lsp.messages; + +import java.util.Objects; + +public record BaselineTokenStyle( + String semanticKey, + String foreground, + boolean italic, + boolean bold, + boolean underline) { + + public BaselineTokenStyle { + semanticKey = requireText(semanticKey, "semanticKey"); + foreground = requireText(foreground, "foreground"); + } + + private static String requireText( + final String value, + final String field) { + final String candidate = Objects.requireNonNull(value, field).trim(); + if (candidate.isEmpty()) { + throw new IllegalArgumentException(field + " must not be blank"); + } + return candidate; + } +} diff --git a/prometeu-lsp/prometeu-lsp-v1/src/main/java/p/studio/lsp/messages/BaselineVisualTheme.java b/prometeu-lsp/prometeu-lsp-v1/src/main/java/p/studio/lsp/messages/BaselineVisualTheme.java new file mode 100644 index 00000000..63145a86 --- /dev/null +++ b/prometeu-lsp/prometeu-lsp-v1/src/main/java/p/studio/lsp/messages/BaselineVisualTheme.java @@ -0,0 +1,31 @@ +package p.studio.lsp.messages; + +import java.util.List; +import java.util.Objects; + +public record BaselineVisualTheme( + String themeId, + String displayName, + BaselineEditorPalette editorPalette, + List tokenStyles) { + + public BaselineVisualTheme { + themeId = requireText(themeId, "themeId"); + displayName = requireText(displayName, "displayName"); + editorPalette = Objects.requireNonNull(editorPalette, "editorPalette"); + tokenStyles = List.copyOf(Objects.requireNonNull(tokenStyles, "tokenStyles")); + if (tokenStyles.isEmpty()) { + throw new IllegalArgumentException("tokenStyles must not be empty"); + } + } + + private static String requireText( + final String value, + final String field) { + final String candidate = Objects.requireNonNull(value, field).trim(); + if (candidate.isEmpty()) { + throw new IllegalArgumentException(field + " must not be blank"); + } + return candidate; + } +} diff --git a/prometeu-lsp/prometeu-lsp-v1/src/main/java/p/studio/lsp/services/compiler/CompilerLanguageServiceBridge.java b/prometeu-lsp/prometeu-lsp-v1/src/main/java/p/studio/lsp/services/compiler/CompilerLanguageServiceBridge.java index c3a7c27f..787aa02c 100644 --- a/prometeu-lsp/prometeu-lsp-v1/src/main/java/p/studio/lsp/services/compiler/CompilerLanguageServiceBridge.java +++ b/prometeu-lsp/prometeu-lsp-v1/src/main/java/p/studio/lsp/services/compiler/CompilerLanguageServiceBridge.java @@ -5,7 +5,10 @@ import p.studio.compiler.messages.BuilderPipelineConfig; import p.studio.compiler.messages.BuildingIssue; import p.studio.compiler.models.AnalysisSnapshot; import p.studio.compiler.models.BuilderPipelineContext; +import p.studio.compiler.models.FrontendEditorPaletteSpec; import p.studio.compiler.PBSDefinitions; +import p.studio.compiler.models.FrontendTokenStyleSpec; +import p.studio.compiler.models.FrontendVisualThemeSpec; import p.studio.compiler.pbs.PbsSemanticKind; import p.studio.compiler.pbs.lexer.PbsLexer; import p.studio.compiler.pbs.lexer.PbsToken; @@ -34,7 +37,9 @@ public record CompilerLanguageServiceBridge() implements LanguageServiceBridge { "Prometeu Studio LSP", "0.1.0", true, - PBSDefinitions.PBS.getSemanticPresentation().semanticKeys()); + PBSDefinitions.PBS.getSemanticPresentation().semanticKeys(), + PBSDefinitions.PBS.getSemanticPresentation().themes().stream().map(this::mapVisualTheme).toList(), + PBSDefinitions.PBS.getSemanticPresentation().defaultThemeId()); } @Override @@ -190,4 +195,32 @@ public record CompilerLanguageServiceBridge() implements LanguageServiceBridge { return tokens.get(index - 1).kind() == p.studio.compiler.pbs.lexer.PbsTokenKind.LEFT_BRACKET && tokens.get(index + 1).kind() == p.studio.compiler.pbs.lexer.PbsTokenKind.RIGHT_BRACKET; } + + private BaselineVisualTheme mapVisualTheme(final FrontendVisualThemeSpec theme) { + return new BaselineVisualTheme( + theme.themeId(), + theme.displayName(), + mapEditorPalette(theme.editorPalette()), + theme.tokenStyles().stream().map(this::mapTokenStyle).toList()); + } + + private BaselineEditorPalette mapEditorPalette(final FrontendEditorPaletteSpec palette) { + return new BaselineEditorPalette( + palette.baseForeground(), + palette.selectionBackground(), + palette.activeHighlightBackground(), + palette.lineNumberForeground(), + palette.statusChipBackground(), + palette.statusChipBorder(), + palette.statusChipForeground()); + } + + private BaselineTokenStyle mapTokenStyle(final FrontendTokenStyleSpec tokenStyle) { + return new BaselineTokenStyle( + tokenStyle.semanticKey(), + tokenStyle.foreground(), + tokenStyle.italic(), + tokenStyle.bold(), + tokenStyle.underline()); + } } diff --git a/prometeu-lsp/prometeu-lsp-v1/src/test/java/p/studio/lsp/services/compiler/CompilerLanguageServiceBridgeTest.java b/prometeu-lsp/prometeu-lsp-v1/src/test/java/p/studio/lsp/services/compiler/CompilerLanguageServiceBridgeTest.java index c95d6c36..05e009cc 100644 --- a/prometeu-lsp/prometeu-lsp-v1/src/test/java/p/studio/lsp/services/compiler/CompilerLanguageServiceBridgeTest.java +++ b/prometeu-lsp/prometeu-lsp-v1/src/test/java/p/studio/lsp/services/compiler/CompilerLanguageServiceBridgeTest.java @@ -8,6 +8,7 @@ import java.nio.file.Files; import java.nio.file.Path; import static org.junit.jupiter.api.Assertions.assertFalse; +import static org.junit.jupiter.api.Assertions.assertEquals; import static org.junit.jupiter.api.Assertions.assertTrue; class CompilerLanguageServiceBridgeTest { @@ -55,6 +56,21 @@ class CompilerLanguageServiceBridgeTest { assertTrue(semanticTokens.tokens().stream().anyMatch(token -> token.semanticKey().equals("pbs-number"))); } + @Test + void describeServerPublishesFrontendVisualThemes() { + final CompilerLanguageServiceBridge bridge = new CompilerLanguageServiceBridge(); + + final var description = bridge.describeServer(new LspProjectContext("main", "pbs", Path.of("."))); + + assertEquals("pbs-default", description.activeVisualThemeId()); + assertEquals(1, description.visualThemes().size()); + assertEquals("PBS Default", description.visualThemes().getFirst().displayName()); + assertEquals("#d9e2ec", description.visualThemes().getFirst().editorPalette().baseForeground()); + assertTrue(description.visualThemes().getFirst().tokenStyles().stream() + .anyMatch(tokenStyle -> tokenStyle.semanticKey().equals("pbs-keyword") + && tokenStyle.foreground().equals("#569cd6"))); + } + private Path findRepoRoot(final Path start) { var current = start; while (current != null) { diff --git a/prometeu-lsp/prometeu-lsp-v1/src/test/java/p/studio/lsp/services/protocol/PrometeuLanguageServerTest.java b/prometeu-lsp/prometeu-lsp-v1/src/test/java/p/studio/lsp/services/protocol/PrometeuLanguageServerTest.java index 33ae0009..10e8e769 100644 --- a/prometeu-lsp/prometeu-lsp-v1/src/test/java/p/studio/lsp/services/protocol/PrometeuLanguageServerTest.java +++ b/prometeu-lsp/prometeu-lsp-v1/src/test/java/p/studio/lsp/services/protocol/PrometeuLanguageServerTest.java @@ -12,9 +12,12 @@ import org.eclipse.lsp4j.services.LanguageClient; import org.eclipse.lsp4j.services.TextDocumentService; import org.junit.jupiter.api.Test; import p.studio.lsp.messages.BaselineDocumentAnalysis; +import p.studio.lsp.messages.BaselineEditorPalette; import p.studio.lsp.messages.BaselineHover; import p.studio.lsp.messages.BaselineSemanticTokens; import p.studio.lsp.messages.BaselineServerDescription; +import p.studio.lsp.messages.BaselineTokenStyle; +import p.studio.lsp.messages.BaselineVisualTheme; import p.studio.lsp.messages.LspProjectContext; import p.studio.lsp.services.LanguageServiceBridge; import p.studio.lsp.services.protocol.mapping.ProtocolMessageMapper; @@ -79,7 +82,17 @@ class PrometeuLanguageServerTest { private static final class RecordingBridge implements LanguageServiceBridge { private int describeServerCalls; - private final BaselineServerDescription serverDescription = new BaselineServerDescription("demo", "1", true, List.of()); + private final BaselineServerDescription serverDescription = new BaselineServerDescription( + "demo", + "1", + true, + List.of(), + List.of(new BaselineVisualTheme( + "demo-default", + "Demo Default", + new BaselineEditorPalette("#111111", "#222222", "#333333", "#444444", "#555555", "#666666", "#777777"), + List.of(new BaselineTokenStyle("demo-keyword", "#888888", false, false, false)))), + "demo-default"); @Override public BaselineServerDescription describeServer(final LspProjectContext project) { -- 2.47.2 From ed2070c5a4803a8ae2ea6adf049b6b30a3276ded Mon Sep 17 00:00:00 2001 From: bQUARKz Date: Wed, 6 May 2026 13:49:58 +0100 Subject: [PATCH 20/37] implements PLN-0070 --- prometeu-studio/build.gradle.kts | 1 + .../FrontendVisualThemeCssRenderer.java | 69 +++++++++++++++++++ .../FrontendVisualThemeCssRendererTest.java | 25 +++++++ 3 files changed, 95 insertions(+) create mode 100644 prometeu-studio/src/main/java/p/studio/utilities/FrontendVisualThemeCssRenderer.java create mode 100644 prometeu-studio/src/test/java/p/studio/utilities/FrontendVisualThemeCssRendererTest.java diff --git a/prometeu-studio/build.gradle.kts b/prometeu-studio/build.gradle.kts index 93d2ea90..4993f398 100644 --- a/prometeu-studio/build.gradle.kts +++ b/prometeu-studio/build.gradle.kts @@ -14,6 +14,7 @@ dependencies { implementation(libs.javafx.controls) implementation(libs.javafx.fxml) implementation(libs.richtextfx) + testImplementation(project(":prometeu-compiler:frontends:prometeu-frontend-pbs")) testImplementation(project(":prometeu-packer:prometeu-packer-v1")) } diff --git a/prometeu-studio/src/main/java/p/studio/utilities/FrontendVisualThemeCssRenderer.java b/prometeu-studio/src/main/java/p/studio/utilities/FrontendVisualThemeCssRenderer.java new file mode 100644 index 00000000..24fef5ab --- /dev/null +++ b/prometeu-studio/src/main/java/p/studio/utilities/FrontendVisualThemeCssRenderer.java @@ -0,0 +1,69 @@ +package p.studio.utilities; + +import p.studio.compiler.models.FrontendSemanticPresentationSpec; +import p.studio.compiler.models.FrontendTokenStyleSpec; +import p.studio.compiler.models.FrontendVisualThemeSpec; + +import java.util.Objects; + +public final class FrontendVisualThemeCssRenderer { + + public String renderDefaultTheme( + final String languageId, + final FrontendSemanticPresentationSpec presentation) { + Objects.requireNonNull(presentation, "presentation"); + return renderTheme(languageId, presentation.defaultTheme()); + } + + public String renderTheme( + final String languageId, + final FrontendVisualThemeSpec theme) { + final String normalizedLanguageId = requireText(languageId, "languageId"); + final FrontendVisualThemeSpec resolvedTheme = Objects.requireNonNull(theme, "theme"); + final String editorSelector = ".editor-workspace-code-area-type-" + normalizedLanguageId; + final String statusChipSelector = ".editor-workspace-status-chip-type-" + normalizedLanguageId; + final StringBuilder css = new StringBuilder(); + + css.append(editorSelector).append(" {\n") + .append(" -fx-highlight-fill: ").append(resolvedTheme.editorPalette().activeHighlightBackground()).append(";\n") + .append("}\n\n") + .append(editorSelector).append(" .text {\n") + .append(" -fx-fill: ").append(resolvedTheme.editorPalette().baseForeground()).append(";\n") + .append("}\n\n") + .append(editorSelector).append(" .lineno {\n") + .append(" -fx-text-fill: ").append(resolvedTheme.editorPalette().lineNumberForeground()).append(";\n") + .append("}\n\n"); + + for (final FrontendTokenStyleSpec tokenStyle : resolvedTheme.tokenStyles()) { + css.append(editorSelector).append(" .text.editor-semantic-").append(tokenStyle.semanticKey()).append(" {\n") + .append(" -fx-fill: ").append(tokenStyle.foreground()).append(";\n"); + if (tokenStyle.italic()) { + css.append(" -fx-font-style: italic;\n"); + } + if (tokenStyle.bold()) { + css.append(" -fx-font-weight: bold;\n"); + } + if (tokenStyle.underline()) { + css.append(" -fx-underline: true;\n"); + } + css.append("}\n\n"); + } + + css.append(statusChipSelector).append(" {\n") + .append(" -fx-background-color: ").append(resolvedTheme.editorPalette().statusChipBackground()).append(";\n") + .append(" -fx-border-color: ").append(resolvedTheme.editorPalette().statusChipBorder()).append(";\n") + .append(" -fx-text-fill: ").append(resolvedTheme.editorPalette().statusChipForeground()).append(";\n") + .append("}\n"); + return css.toString(); + } + + private static String requireText( + final String value, + final String field) { + final String candidate = Objects.requireNonNull(value, field).trim(); + if (candidate.isEmpty()) { + throw new IllegalArgumentException(field + " must not be blank"); + } + return candidate; + } +} diff --git a/prometeu-studio/src/test/java/p/studio/utilities/FrontendVisualThemeCssRendererTest.java b/prometeu-studio/src/test/java/p/studio/utilities/FrontendVisualThemeCssRendererTest.java new file mode 100644 index 00000000..3f4b2a17 --- /dev/null +++ b/prometeu-studio/src/test/java/p/studio/utilities/FrontendVisualThemeCssRendererTest.java @@ -0,0 +1,25 @@ +package p.studio.utilities; + +import org.junit.jupiter.api.Test; +import p.studio.compiler.PBSDefinitions; + +import static org.junit.jupiter.api.Assertions.assertTrue; + +class FrontendVisualThemeCssRendererTest { + + @Test + void rendersLegacyCompatibleCssFromStructuredFrontendTheme() { + final FrontendVisualThemeCssRenderer renderer = new FrontendVisualThemeCssRenderer(); + + final String css = renderer.renderDefaultTheme( + PBSDefinitions.PBS.getLanguageId(), + PBSDefinitions.PBS.getSemanticPresentation()); + + assertTrue(css.contains(".editor-workspace-code-area-type-pbs")); + assertTrue(css.contains(".text.editor-semantic-pbs-keyword")); + assertTrue(css.contains("-fx-fill: #569cd6;")); + assertTrue(css.contains("-fx-font-style: italic;")); + assertTrue(css.contains(".editor-workspace-status-chip-type-pbs")); + assertTrue(css.contains("-fx-border-color: #a47dff;")); + } +} -- 2.47.2 From 69f5c4abdd21f4bf77490ee4f48881bc53e40423 Mon Sep 17 00:00:00 2001 From: bQUARKz Date: Wed, 6 May 2026 13:53:23 +0100 Subject: [PATCH 21/37] implements PLN-0071 --- .../messages/BaselineServerDescription.java | 2 + .../CompilerLanguageServiceBridge.java | 1 + .../mapping/Lsp4jProtocolMessageMapper.java | 29 ++ .../CompilerLanguageServiceBridgeTest.java | 1 + .../protocol/PrometeuLanguageServerTest.java | 2 + tools/vscode-extension/out/extension.js | 292 ++++++++++++++++++ tools/vscode-extension/package.json | 36 +-- tools/vscode-extension/src/extension.ts | 141 +++++++++ 8 files changed, 469 insertions(+), 35 deletions(-) create mode 100644 tools/vscode-extension/out/extension.js diff --git a/prometeu-lsp/prometeu-lsp-v1/src/main/java/p/studio/lsp/messages/BaselineServerDescription.java b/prometeu-lsp/prometeu-lsp-v1/src/main/java/p/studio/lsp/messages/BaselineServerDescription.java index daf47a62..9734f319 100644 --- a/prometeu-lsp/prometeu-lsp-v1/src/main/java/p/studio/lsp/messages/BaselineServerDescription.java +++ b/prometeu-lsp/prometeu-lsp-v1/src/main/java/p/studio/lsp/messages/BaselineServerDescription.java @@ -6,6 +6,7 @@ import java.util.List; public record BaselineServerDescription( String name, String version, + String frontendLanguageId, boolean hoverSupported, List semanticTokenTypes, List visualThemes, @@ -14,6 +15,7 @@ public record BaselineServerDescription( public BaselineServerDescription { name = requireText(name, "name"); version = requireText(version, "version"); + frontendLanguageId = requireText(frontendLanguageId, "frontendLanguageId"); semanticTokenTypes = List.copyOf(Objects.requireNonNull(semanticTokenTypes, "semanticTokenTypes")); visualThemes = List.copyOf(Objects.requireNonNull(visualThemes, "visualThemes")); activeVisualThemeId = requireText(activeVisualThemeId, "activeVisualThemeId"); diff --git a/prometeu-lsp/prometeu-lsp-v1/src/main/java/p/studio/lsp/services/compiler/CompilerLanguageServiceBridge.java b/prometeu-lsp/prometeu-lsp-v1/src/main/java/p/studio/lsp/services/compiler/CompilerLanguageServiceBridge.java index 787aa02c..534c3ffa 100644 --- a/prometeu-lsp/prometeu-lsp-v1/src/main/java/p/studio/lsp/services/compiler/CompilerLanguageServiceBridge.java +++ b/prometeu-lsp/prometeu-lsp-v1/src/main/java/p/studio/lsp/services/compiler/CompilerLanguageServiceBridge.java @@ -36,6 +36,7 @@ public record CompilerLanguageServiceBridge() implements LanguageServiceBridge { return new BaselineServerDescription( "Prometeu Studio LSP", "0.1.0", + context.languageId(), true, PBSDefinitions.PBS.getSemanticPresentation().semanticKeys(), PBSDefinitions.PBS.getSemanticPresentation().themes().stream().map(this::mapVisualTheme).toList(), diff --git a/prometeu-lsp/prometeu-lsp-v1/src/main/java/p/studio/lsp/services/protocol/mapping/Lsp4jProtocolMessageMapper.java b/prometeu-lsp/prometeu-lsp-v1/src/main/java/p/studio/lsp/services/protocol/mapping/Lsp4jProtocolMessageMapper.java index 28d8cf8d..aba2dd5f 100644 --- a/prometeu-lsp/prometeu-lsp-v1/src/main/java/p/studio/lsp/services/protocol/mapping/Lsp4jProtocolMessageMapper.java +++ b/prometeu-lsp/prometeu-lsp-v1/src/main/java/p/studio/lsp/services/protocol/mapping/Lsp4jProtocolMessageMapper.java @@ -5,7 +5,9 @@ import p.studio.lsp.messages.*; import java.util.ArrayList; import java.util.Comparator; +import java.util.LinkedHashMap; import java.util.List; +import java.util.Map; public final class Lsp4jProtocolMessageMapper implements ProtocolMessageMapper { @Override @@ -26,6 +28,12 @@ public final class Lsp4jProtocolMessageMapper implements ProtocolMessageMapper { semanticTokens.setLegend(new SemanticTokensLegend(description.semanticTokenTypes(), List.of())); semanticTokens.setFull(true); capabilities.setSemanticTokensProvider(semanticTokens); + capabilities.setExperimental(Map.of( + "prometeuVisualThemes", + Map.of( + "frontendLanguageId", description.frontendLanguageId(), + "activeVisualThemeId", description.activeVisualThemeId(), + "visualThemes", description.visualThemes().stream().map(this::mapVisualThemePayload).toList()))); final InitializeResult result = new InitializeResult(capabilities); final ServerInfo serverInfo = new ServerInfo(); @@ -122,4 +130,25 @@ public final class Lsp4jProtocolMessageMapper implements ProtocolMessageMapper { case ERROR -> DiagnosticSeverity.Error; }; } + + private Map mapVisualThemePayload(final BaselineVisualTheme theme) { + final Map payload = new LinkedHashMap<>(); + payload.put("themeId", theme.themeId()); + payload.put("displayName", theme.displayName()); + payload.put("editorPalette", Map.of( + "baseForeground", theme.editorPalette().baseForeground(), + "selectionBackground", theme.editorPalette().selectionBackground(), + "activeHighlightBackground", theme.editorPalette().activeHighlightBackground(), + "lineNumberForeground", theme.editorPalette().lineNumberForeground(), + "statusChipBackground", theme.editorPalette().statusChipBackground(), + "statusChipBorder", theme.editorPalette().statusChipBorder(), + "statusChipForeground", theme.editorPalette().statusChipForeground())); + payload.put("tokenStyles", theme.tokenStyles().stream().map(tokenStyle -> Map.of( + "semanticKey", tokenStyle.semanticKey(), + "foreground", tokenStyle.foreground(), + "italic", tokenStyle.italic(), + "bold", tokenStyle.bold(), + "underline", tokenStyle.underline())).toList()); + return payload; + } } diff --git a/prometeu-lsp/prometeu-lsp-v1/src/test/java/p/studio/lsp/services/compiler/CompilerLanguageServiceBridgeTest.java b/prometeu-lsp/prometeu-lsp-v1/src/test/java/p/studio/lsp/services/compiler/CompilerLanguageServiceBridgeTest.java index 05e009cc..e613bb54 100644 --- a/prometeu-lsp/prometeu-lsp-v1/src/test/java/p/studio/lsp/services/compiler/CompilerLanguageServiceBridgeTest.java +++ b/prometeu-lsp/prometeu-lsp-v1/src/test/java/p/studio/lsp/services/compiler/CompilerLanguageServiceBridgeTest.java @@ -62,6 +62,7 @@ class CompilerLanguageServiceBridgeTest { final var description = bridge.describeServer(new LspProjectContext("main", "pbs", Path.of("."))); + assertEquals("pbs", description.frontendLanguageId()); assertEquals("pbs-default", description.activeVisualThemeId()); assertEquals(1, description.visualThemes().size()); assertEquals("PBS Default", description.visualThemes().getFirst().displayName()); diff --git a/prometeu-lsp/prometeu-lsp-v1/src/test/java/p/studio/lsp/services/protocol/PrometeuLanguageServerTest.java b/prometeu-lsp/prometeu-lsp-v1/src/test/java/p/studio/lsp/services/protocol/PrometeuLanguageServerTest.java index 10e8e769..f59b745c 100644 --- a/prometeu-lsp/prometeu-lsp-v1/src/test/java/p/studio/lsp/services/protocol/PrometeuLanguageServerTest.java +++ b/prometeu-lsp/prometeu-lsp-v1/src/test/java/p/studio/lsp/services/protocol/PrometeuLanguageServerTest.java @@ -55,6 +55,7 @@ class PrometeuLanguageServerTest { assertSame(expected, result); assertEquals(1, bridge.describeServerCalls); assertSame(bridge.serverDescription, mapper.lastServerDescription); + assertEquals("pbs", bridge.serverDescription.frontendLanguageId()); } @Test @@ -85,6 +86,7 @@ class PrometeuLanguageServerTest { private final BaselineServerDescription serverDescription = new BaselineServerDescription( "demo", "1", + "pbs", true, List.of(), List.of(new BaselineVisualTheme( diff --git a/tools/vscode-extension/out/extension.js b/tools/vscode-extension/out/extension.js new file mode 100644 index 00000000..bd27beb0 --- /dev/null +++ b/tools/vscode-extension/out/extension.js @@ -0,0 +1,292 @@ +"use strict"; +var __createBinding = (this && this.__createBinding) || (Object.create ? (function(o, m, k, k2) { + if (k2 === undefined) k2 = k; + var desc = Object.getOwnPropertyDescriptor(m, k); + if (!desc || ("get" in desc ? !m.__esModule : desc.writable || desc.configurable)) { + desc = { enumerable: true, get: function() { return m[k]; } }; + } + Object.defineProperty(o, k2, desc); +}) : (function(o, m, k, k2) { + if (k2 === undefined) k2 = k; + o[k2] = m[k]; +})); +var __setModuleDefault = (this && this.__setModuleDefault) || (Object.create ? (function(o, v) { + Object.defineProperty(o, "default", { enumerable: true, value: v }); +}) : function(o, v) { + o["default"] = v; +}); +var __importStar = (this && this.__importStar) || (function () { + var ownKeys = function(o) { + ownKeys = Object.getOwnPropertyNames || function (o) { + var ar = []; + for (var k in o) if (Object.prototype.hasOwnProperty.call(o, k)) ar[ar.length] = k; + return ar; + }; + return ownKeys(o); + }; + return function (mod) { + if (mod && mod.__esModule) return mod; + var result = {}; + if (mod != null) for (var k = ownKeys(mod), i = 0; i < k.length; i++) if (k[i] !== "default") __createBinding(result, mod, k[i]); + __setModuleDefault(result, mod); + return result; + }; +})(); +Object.defineProperty(exports, "__esModule", { value: true }); +exports.activate = activate; +exports.deactivate = deactivate; +const net = __importStar(require("node:net")); +const vscode = __importStar(require("vscode")); +const node_1 = require("vscode-languageclient/node"); +let client; +let output; +let reconnectTimer; +let reconnectContext; +let stoppingClient = false; +let lastAppliedThemeSignature; +const RECONNECT_DELAY_MS = 2000; +function activate(context) { + reconnectContext = context; + output = vscode.window.createOutputChannel("Prometeu LSP"); + output.appendLine("Prometeu VS Code extension activated."); + const connectCommand = vscode.commands.registerCommand("prometeu.connectStudioLsp", async () => { + await startClient(context); + }); + const restartCommand = vscode.commands.registerCommand("prometeu.restartStudioLsp", async () => { + await stopClient(); + await startClient(context); + }); + context.subscriptions.push(output, connectCommand, restartCommand); + void startClient(context); +} +async function deactivate() { + await stopClient(); +} +async function startClient(context) { + clearReconnectTimer(); + if (client) { + output.appendLine("Prometeu LSP client is already running."); + return; + } + const config = vscode.workspace.getConfiguration("prometeu.studio"); + const host = config.get("host", "127.0.0.1"); + const port = config.get("port", 7775); + output.show(true); + output.appendLine(`Connecting to Prometeu Studio LSP at ${host}:${port}...`); + const serverOptions = async () => { + return new Promise((resolve, reject) => { + const socket = net.createConnection({ host, port }); + let settled = false; + const connectTimeout = setTimeout(() => { + if (settled) { + return; + } + settled = true; + socket.destroy(); + reject(new Error("Connection timed out.")); + }, 3000); + socket.once("connect", () => { + if (settled) { + return; + } + settled = true; + clearTimeout(connectTimeout); + output.appendLine("TCP connection established with Prometeu Studio."); + resolve({ + reader: socket, + writer: socket + }); + }); + socket.once("error", (error) => { + if (settled) { + return; + } + settled = true; + clearTimeout(connectTimeout); + reject(error); + }); + }); + }; + const clientOptions = { + documentSelector: [ + { + scheme: "file", + language: "pbs" + } + ], + synchronize: { + fileEvents: [ + vscode.workspace.createFileSystemWatcher("**/*.pbs") + ] + }, + initializationOptions: { + clientKind: "vscode", + prometeuClientVersion: context.extension.packageJSON.version + }, + outputChannel: output, + errorHandler: { + error: (error) => { + output.appendLine(`Prometeu LSP transport error: ${error.message}`); + return { action: node_1.ErrorAction.Continue }; + }, + closed: () => { + output.appendLine("Prometeu LSP transport closed."); + return { action: node_1.CloseAction.DoNotRestart }; + } + } + }; + const nextClient = new node_1.LanguageClient("prometeuStudioLsp", "Prometeu Studio LSP", serverOptions, clientOptions); + client = nextClient; + nextClient.onDidChangeState((event) => { + output.appendLine(`Prometeu LSP state changed: ${node_1.State[event.oldState]} -> ${node_1.State[event.newState]}`); + if (event.newState !== node_1.State.Stopped) { + return; + } + if (client === nextClient) { + client = undefined; + } + if (!stoppingClient) { + scheduleReconnect(); + } + }); + try { + await nextClient.start(); + await applyPrometeuVisualTheme(nextClient.initializeResult); + output.appendLine("Prometeu Studio LSP client started."); + vscode.window.showInformationMessage("Connected to Prometeu Studio LSP."); + } + catch (error) { + if (client === nextClient) { + client = undefined; + } + const message = error instanceof Error ? error.message : String(error); + output.appendLine(`Failed to start Prometeu LSP client: ${message}`); + vscode.window.showErrorMessage(`Could not connect to Prometeu Studio LSP: ${message}`); + scheduleReconnect(); + } +} +async function stopClient() { + clearReconnectTimer(); + if (!client) { + return; + } + const currentClient = client; + client = undefined; + stoppingClient = true; + output.appendLine("Stopping Prometeu Studio LSP client..."); + try { + await currentClient.stop(); + output.appendLine("Prometeu Studio LSP client stopped."); + } + catch (error) { + const message = error instanceof Error ? error.message : String(error); + output.appendLine(`Failed to stop Prometeu LSP client cleanly: ${message}`); + } + finally { + stoppingClient = false; + } +} +function scheduleReconnect() { + if (!reconnectContext) { + return; + } + if (reconnectTimer || client) { + return; + } + output.appendLine(`Scheduling Prometeu LSP reconnect in ${RECONNECT_DELAY_MS}ms...`); + reconnectTimer = setTimeout(() => { + reconnectTimer = undefined; + void startClient(reconnectContext); + }, RECONNECT_DELAY_MS); +} +function clearReconnectTimer() { + if (!reconnectTimer) { + return; + } + clearTimeout(reconnectTimer); + reconnectTimer = undefined; +} +async function applyPrometeuVisualTheme(initializeResult) { + const payload = extractPrometeuVisualThemesPayload(initializeResult); + if (!payload) { + output.appendLine("Prometeu visual theme payload not present in initialize result."); + return; + } + const activeTheme = payload.visualThemes.find((theme) => theme.themeId === payload.activeVisualThemeId); + if (!activeTheme) { + output.appendLine(`Prometeu visual theme '${payload.activeVisualThemeId}' was not declared by the server.`); + return; + } + const themeSignature = JSON.stringify({ + languageId: payload.frontendLanguageId, + themeId: activeTheme.themeId, + editorPalette: activeTheme.editorPalette, + tokenStyles: activeTheme.tokenStyles + }); + if (themeSignature === lastAppliedThemeSignature) { + output.appendLine(`Prometeu visual theme '${activeTheme.themeId}' is already applied.`); + return; + } + const configurationTarget = vscode.workspace.workspaceFolders?.length + ? vscode.ConfigurationTarget.Workspace + : vscode.ConfigurationTarget.Global; + const configuration = vscode.workspace.getConfiguration(); + const existingSemanticCustomizations = configuration.get("editor.semanticTokenColorCustomizations") ?? {}; + const semanticRules = { + ...(readObject(existingSemanticCustomizations.rules)), + ...buildSemanticTokenRules(payload.frontendLanguageId, activeTheme) + }; + await configuration.update("editor.semanticTokenColorCustomizations", { + ...existingSemanticCustomizations, + enabled: true, + rules: semanticRules + }, configurationTarget); + const existingWorkbenchColors = configuration.get("workbench.colorCustomizations") ?? {}; + await configuration.update("workbench.colorCustomizations", { + ...existingWorkbenchColors, + "editor.foreground": activeTheme.editorPalette.baseForeground, + "editor.selectionBackground": activeTheme.editorPalette.selectionBackground, + "editorLineNumber.foreground": activeTheme.editorPalette.lineNumberForeground + }, configurationTarget); + lastAppliedThemeSignature = themeSignature; + output.appendLine(`Applied Prometeu visual theme '${activeTheme.themeId}' for language '${payload.frontendLanguageId}'.`); +} +function extractPrometeuVisualThemesPayload(initializeResult) { + if (!initializeResult || typeof initializeResult !== "object") { + return undefined; + } + const capabilities = readObject(initializeResult.capabilities); + const experimental = readObject(capabilities.experimental); + const payload = readObject(experimental.prometeuVisualThemes); + if (typeof payload.frontendLanguageId !== "string" || typeof payload.activeVisualThemeId !== "string") { + return undefined; + } + if (!Array.isArray(payload.visualThemes)) { + return undefined; + } + return payload; +} +function buildSemanticTokenRules(languageId, theme) { + const rules = {}; + for (const tokenStyle of theme.tokenStyles) { + const selector = `${tokenStyle.semanticKey}:${languageId}`; + if (!tokenStyle.italic && !tokenStyle.bold && !tokenStyle.underline) { + rules[selector] = tokenStyle.foreground; + continue; + } + rules[selector] = { + foreground: tokenStyle.foreground, + ...(tokenStyle.italic ? { italic: true } : {}), + ...(tokenStyle.bold ? { bold: true } : {}), + ...(tokenStyle.underline ? { underline: true } : {}) + }; + } + return rules; +} +function readObject(value) { + if (!value || typeof value !== "object" || Array.isArray(value)) { + return {}; + } + return value; +} +//# sourceMappingURL=extension.js.map diff --git a/tools/vscode-extension/package.json b/tools/vscode-extension/package.json index 425b945d..f370837e 100644 --- a/tools/vscode-extension/package.json +++ b/tools/vscode-extension/package.json @@ -148,41 +148,7 @@ } ], "configurationDefaults": { - "editor.semanticHighlighting.enabled": true, - "editor.semanticTokenColorCustomizations": { - "enabled": true, - "rules": { - "pbs-keyword:pbs": "#569cd6", - "pbs-lifecycle:pbs": "#ef50c0", - "pbs-function:pbs": "#f2c14e", - "pbs-method:pbs": "#f2c14e", - "pbs-constructor:pbs": "#ecdcaa", - "pbs-struct:pbs": "#4ec9b0", - "pbs-contract:pbs": "#78dce8", - "pbs-host:pbs": "#b7a2fa", - "pbs-builtin-type:pbs": "#8be9fd", - "pbs-service:pbs": "#b7a2fa", - "pbs-error:pbs": "#ff5b5b", - "pbs-enum:pbs": "#56cfe1", - "pbs-callback:pbs": "#b7a2fa", - "pbs-global:pbs": { - "foreground": "#f790fc", - "italic": true - }, - "pbs-const:pbs": "#f78c6c", - "pbs-implements:pbs": "#a1c181", - "pbs-string:pbs": "#00c088", - "pbs-number:pbs": "#ff90b0", - "pbs-comment:pbs": { - "foreground": "#c090b0", - "italic": true - }, - "pbs-literal:pbs": "#4fc1ff", - "pbs-operator:pbs": "#d4d4d4", - "pbs-punctuation:pbs": "#d4d4d4", - "pbs-identifier:pbs": "#d4d4d4" - } - } + "editor.semanticHighlighting.enabled": true } }, "scripts": { diff --git a/tools/vscode-extension/src/extension.ts b/tools/vscode-extension/src/extension.ts index 82e99904..19d7a1b5 100644 --- a/tools/vscode-extension/src/extension.ts +++ b/tools/vscode-extension/src/extension.ts @@ -16,9 +16,41 @@ let output: vscode.OutputChannel; let reconnectTimer: NodeJS.Timeout | undefined; let reconnectContext: vscode.ExtensionContext | undefined; let stoppingClient = false; +let lastAppliedThemeSignature: string | undefined; const RECONNECT_DELAY_MS = 2000; +type PrometeuTokenStyle = { + semanticKey: string; + foreground: string; + italic: boolean; + bold: boolean; + underline: boolean; +}; + +type PrometeuEditorPalette = { + baseForeground: string; + selectionBackground: string; + activeHighlightBackground: string; + lineNumberForeground: string; + statusChipBackground: string; + statusChipBorder: string; + statusChipForeground: string; +}; + +type PrometeuVisualTheme = { + themeId: string; + displayName: string; + editorPalette: PrometeuEditorPalette; + tokenStyles: PrometeuTokenStyle[]; +}; + +type PrometeuVisualThemesPayload = { + frontendLanguageId: string; + activeVisualThemeId: string; + visualThemes: PrometeuVisualTheme[]; +}; + export function activate(context: vscode.ExtensionContext): void { reconnectContext = context; output = vscode.window.createOutputChannel("Prometeu LSP"); @@ -160,6 +192,7 @@ async function startClient(context: vscode.ExtensionContext): Promise { try { await nextClient.start(); + await applyPrometeuVisualTheme(nextClient.initializeResult); output.appendLine("Prometeu Studio LSP client started."); vscode.window.showInformationMessage("Connected to Prometeu Studio LSP."); @@ -220,3 +253,111 @@ function clearReconnectTimer(): void { clearTimeout(reconnectTimer); reconnectTimer = undefined; } + +async function applyPrometeuVisualTheme(initializeResult: unknown): Promise { + const payload = extractPrometeuVisualThemesPayload(initializeResult); + if (!payload) { + output.appendLine("Prometeu visual theme payload not present in initialize result."); + return; + } + + const activeTheme = payload.visualThemes.find((theme) => theme.themeId === payload.activeVisualThemeId); + if (!activeTheme) { + output.appendLine(`Prometeu visual theme '${payload.activeVisualThemeId}' was not declared by the server.`); + return; + } + + const themeSignature = JSON.stringify({ + languageId: payload.frontendLanguageId, + themeId: activeTheme.themeId, + editorPalette: activeTheme.editorPalette, + tokenStyles: activeTheme.tokenStyles + }); + if (themeSignature === lastAppliedThemeSignature) { + output.appendLine(`Prometeu visual theme '${activeTheme.themeId}' is already applied.`); + return; + } + + const configurationTarget = vscode.workspace.workspaceFolders?.length + ? vscode.ConfigurationTarget.Workspace + : vscode.ConfigurationTarget.Global; + const configuration = vscode.workspace.getConfiguration(); + + const existingSemanticCustomizations = configuration.get>("editor.semanticTokenColorCustomizations") ?? {}; + const semanticRules = { + ...(readObject(existingSemanticCustomizations.rules)), + ...buildSemanticTokenRules(payload.frontendLanguageId, activeTheme) + }; + + await configuration.update( + "editor.semanticTokenColorCustomizations", + { + ...existingSemanticCustomizations, + enabled: true, + rules: semanticRules + }, + configurationTarget + ); + + const existingWorkbenchColors = configuration.get>("workbench.colorCustomizations") ?? {}; + await configuration.update( + "workbench.colorCustomizations", + { + ...existingWorkbenchColors, + "editor.foreground": activeTheme.editorPalette.baseForeground, + "editor.selectionBackground": activeTheme.editorPalette.selectionBackground, + "editorLineNumber.foreground": activeTheme.editorPalette.lineNumberForeground + }, + configurationTarget + ); + + lastAppliedThemeSignature = themeSignature; + output.appendLine(`Applied Prometeu visual theme '${activeTheme.themeId}' for language '${payload.frontendLanguageId}'.`); +} + +function extractPrometeuVisualThemesPayload(initializeResult: unknown): PrometeuVisualThemesPayload | undefined { + if (!initializeResult || typeof initializeResult !== "object") { + return undefined; + } + + const capabilities = readObject((initializeResult as { capabilities?: unknown }).capabilities); + const experimental = readObject(capabilities.experimental); + const payload = readObject(experimental.prometeuVisualThemes); + + if (typeof payload.frontendLanguageId !== "string" || typeof payload.activeVisualThemeId !== "string") { + return undefined; + } + if (!Array.isArray(payload.visualThemes)) { + return undefined; + } + + return payload as unknown as PrometeuVisualThemesPayload; +} + +function buildSemanticTokenRules( + languageId: string, + theme: PrometeuVisualTheme +): Record { + const rules: Record = {}; + for (const tokenStyle of theme.tokenStyles) { + const selector = `${tokenStyle.semanticKey}:${languageId}`; + if (!tokenStyle.italic && !tokenStyle.bold && !tokenStyle.underline) { + rules[selector] = tokenStyle.foreground; + continue; + } + rules[selector] = { + foreground: tokenStyle.foreground, + ...(tokenStyle.italic ? { italic: true } : {}), + ...(tokenStyle.bold ? { bold: true } : {}), + ...(tokenStyle.underline ? { underline: true } : {}) + }; + } + return rules; +} + +function readObject(value: unknown): Record { + if (!value || typeof value !== "object" || Array.isArray(value)) { + return {}; + } + return value as Record; +} -- 2.47.2 From cab0e92e60dfef074690793cf627e0c1233c4336 Mon Sep 17 00:00:00 2001 From: bQUARKz Date: Wed, 6 May 2026 15:21:15 +0100 Subject: [PATCH 22/37] Frontend Visual Theme Spec and Retirement of Host-Consumed Semantic CSS --- discussion/index.ndjson | 3 +- ...nd-semantic-host-projection-flexibility.md | 85 +++++++++++++ ...nd-semantic-host-projection-flexibility.md | 112 +++++++++++++++++ ...ntend-semantic-host-projection-contract.md | 119 ++++++++++++++++++ ...-lsp-semantic-host-projection-transport.md | 107 ++++++++++++++++ ...vscode-semantic-host-projection-adapter.md | 109 ++++++++++++++++ .../p/studio/compiler/PBSDefinitions.java | 41 +----- .../p/studio/compiler/PBSFrontendThemes.java | 45 +++++++ test-projects/main/.vscode/settings.json | 41 ++++++ tools/vscode-extension/out/extension.js | 2 +- 10 files changed, 623 insertions(+), 41 deletions(-) create mode 100644 discussion/workflow/agendas/AGD-0037-frontend-semantic-host-projection-flexibility.md create mode 100644 discussion/workflow/decisions/DEC-0034-frontend-semantic-host-projection-flexibility.md create mode 100644 discussion/workflow/plans/PLN-0072-frontend-semantic-host-projection-contract.md create mode 100644 discussion/workflow/plans/PLN-0073-lsp-semantic-host-projection-transport.md create mode 100644 discussion/workflow/plans/PLN-0074-vscode-semantic-host-projection-adapter.md create mode 100644 prometeu-compiler/frontends/prometeu-frontend-pbs/src/main/java/p/studio/compiler/PBSFrontendThemes.java create mode 100644 test-projects/main/.vscode/settings.json diff --git a/discussion/index.ndjson b/discussion/index.ndjson index 9cf19490..4369e623 100644 --- a/discussion/index.ndjson +++ b/discussion/index.ndjson @@ -1,4 +1,5 @@ -{"type":"meta","next_id":{"DSC":34,"AGD":37,"DEC":34,"PLN":72,"LSN":47,"CLSN":1}} +{"type":"meta","next_id":{"DSC":35,"AGD":38,"DEC":35,"PLN":75,"LSN":47,"CLSN":1}} +{"type":"discussion","id":"DSC-0034","status":"in_progress","ticket":"frontend-semantic-host-projection-flexibility","title":"Frontend semantic vocabulary flexibility and declarative host projection","created_at":"2026-05-06","updated_at":"2026-05-06","tags":["compiler","compiler-general","frontend","semantics","vscode","host-projection","lsp"],"agendas":[{"id":"AGD-0037","file":"AGD-0037-frontend-semantic-host-projection-flexibility.md","status":"accepted","created_at":"2026-05-06","updated_at":"2026-05-06"}],"decisions":[{"id":"DEC-0034","file":"DEC-0034-frontend-semantic-host-projection-flexibility.md","status":"accepted","created_at":"2026-05-06","updated_at":"2026-05-06","ref_agenda":"AGD-0037"}],"plans":[{"id":"PLN-0072","file":"PLN-0072-frontend-semantic-host-projection-contract.md","status":"open","created_at":"2026-05-06","updated_at":"2026-05-06","ref_decisions":["DEC-0034"]},{"id":"PLN-0073","file":"PLN-0073-lsp-semantic-host-projection-transport.md","status":"open","created_at":"2026-05-06","updated_at":"2026-05-06","ref_decisions":["DEC-0034"]},{"id":"PLN-0074","file":"PLN-0074-vscode-semantic-host-projection-adapter.md","status":"open","created_at":"2026-05-06","updated_at":"2026-05-06","ref_decisions":["DEC-0034"]}],"lessons":[]} {"type":"discussion","id":"DSC-0033","status":"in_progress","ticket":"frontend-visual-theme-spec-and-css-retirement","title":"Frontend visual theme spec and retirement of host-consumed semantic CSS","created_at":"2026-05-06","updated_at":"2026-05-06","tags":["compiler","compiler-general","frontend","presentation","theming","studio","vscode","lsp","pbs"],"agendas":[{"id":"AGD-0036","file":"AGD-0036-frontend-visual-theme-spec-and-css-retirement.md","status":"accepted","created_at":"2026-05-06","updated_at":"2026-05-06"}],"decisions":[{"id":"DEC-0033","file":"DEC-0033-frontend-visual-theme-spec-and-css-retirement.md","status":"accepted","created_at":"2026-05-06","updated_at":"2026-05-06","ref_agenda":"AGD-0036"}],"plans":[{"id":"PLN-0068","file":"PLN-0068-frontend-visual-contract-and-pbs-migration.md","status":"open","created_at":"2026-05-06","updated_at":"2026-05-06","ref_decisions":["DEC-0033"]},{"id":"PLN-0069","file":"PLN-0069-lsp-visual-theme-transport-and-selection.md","status":"open","created_at":"2026-05-06","updated_at":"2026-05-06","ref_decisions":["DEC-0033"]},{"id":"PLN-0070","file":"PLN-0070-studio-visual-theme-adapter-and-css-retirement.md","status":"open","created_at":"2026-05-06","updated_at":"2026-05-06","ref_decisions":["DEC-0033"]},{"id":"PLN-0071","file":"PLN-0071-vscode-dynamic-theme-translation-adapter.md","status":"open","created_at":"2026-05-06","updated_at":"2026-05-06","ref_decisions":["DEC-0033"]}],"lessons":[]} {"type":"discussion","id":"DSC-0032","status":"in_progress","ticket":"studio-new-lsp-api-and-v1-boundary","title":"Novo boundary entre lsp-api, lsp-v1 e a extensao VS Code","created_at":"2026-05-05","updated_at":"2026-05-05","tags":["studio","lsp","vscode","protocol","api","boundary"],"agendas":[{"id":"AGD-0035","file":"AGD-0035-studio-new-lsp-api-and-v1-boundary.md","status":"accepted","created_at":"2026-05-05","updated_at":"2026-05-05"}],"decisions":[{"id":"DEC-0032","file":"DEC-0032-studio-new-lsp-api-and-v1-boundary.md","status":"accepted","created_at":"2026-05-05","updated_at":"2026-05-05","ref_agenda":"AGD-0035"}],"plans":[{"id":"PLN-0065","file":"PLN-0065-lsp-boundary-and-module-scaffolding.md","status":"done","created_at":"2026-05-05","updated_at":"2026-05-05","ref_decisions":["DEC-0032"]},{"id":"PLN-0066","file":"PLN-0066-project-scoped-lsp-server-lifecycle-in-studio.md","status":"done","created_at":"2026-05-05","updated_at":"2026-05-05","ref_decisions":["DEC-0032"]},{"id":"PLN-0067","file":"PLN-0067-compiler-backed-dumb-lsp-server-baseline.md","status":"done","created_at":"2026-05-05","updated_at":"2026-05-05","ref_decisions":["DEC-0032"]}],"lessons":[]} {"type":"discussion","id":"DSC-0031","status":"in_progress","ticket":"studio-editor-workspace-cleanup","title":"Limpeza completa do Workspace Editor do Studio e remoção dos acoplamentos legados","created_at":"2026-05-05","updated_at":"2026-05-05","tags":["studio","editor","cleanup","vfs","lsp","migration"],"agendas":[{"id":"AGD-0034","file":"AGD-0034-vscode-editor-migration-feasibility.md","status":"accepted","created_at":"2026-05-05","updated_at":"2026-05-05"}],"decisions":[{"id":"DEC-0031","file":"DEC-0031-studio-editor-workspace-cleanup.md","status":"in_progress","created_at":"2026-05-05","updated_at":"2026-05-05","ref_agenda":"AGD-0034"}],"plans":[{"id":"PLN-0062","file":"PLN-0062-shell-session-and-state-cleanup-after-editor-removal.md","status":"done","created_at":"2026-05-05","updated_at":"2026-05-05","ref_decisions":["DEC-0031"]},{"id":"PLN-0063","file":"PLN-0063-legacy-lsp-and-vfs-module-removal-with-runtime-preservation.md","status":"done","created_at":"2026-05-05","updated_at":"2026-05-05","ref_decisions":["DEC-0031"]},{"id":"PLN-0064","file":"PLN-0064-normative-test-and-lesson-cleanup-for-editor-stack-removal.md","status":"done","created_at":"2026-05-05","updated_at":"2026-05-05","ref_decisions":["DEC-0031"]}],"lessons":[]} diff --git a/discussion/workflow/agendas/AGD-0037-frontend-semantic-host-projection-flexibility.md b/discussion/workflow/agendas/AGD-0037-frontend-semantic-host-projection-flexibility.md new file mode 100644 index 00000000..59216d56 --- /dev/null +++ b/discussion/workflow/agendas/AGD-0037-frontend-semantic-host-projection-flexibility.md @@ -0,0 +1,85 @@ +--- +id: AGD-0037 +ticket: frontend-semantic-host-projection-flexibility +title: Frontend Semantic Vocabulary Flexibility and Host Projection +status: accepted +created: 2026-05-06 +resolved: 2026-05-06 +decision: DEC-0034 +tags: [compiler, compiler-general, frontend, semantics, vscode, host-projection, lsp] +--- + +## Pain + +The current discussion exposed an architectural tension: + +- frontend semantic keys must remain frontend-owned and flexible, +- but VS Code prefers host-shaped semantic token categories and modifiers, +- and forcing frontend vocabularies into a rigid global taxonomy would collapse frontend ownership into host constraints. + +If Prometeu treats VS Code semantic categories as the canonical semantic contract, the frontend loses semantic freedom and the wrong layer starts owning language meaning. + +## Context + +Domain owner: `compiler/general` + +This discussion extends `DEC-0033` rather than replacing it. +`DEC-0033` already locked that visual themes are frontend-owned and hosts are adapters. + +What remained implicit was how a frontend-owned semantic vocabulary should adapt to host capabilities when the host prefers a different semantic model. + +The key clarification is: + +- the frontend semantic vocabulary remains canonical, +- host adaptation is declarative projection, +- host projection does not become the canonical semantic contract. + +## Open Questions + +- [x] Should Prometeu define a rigid global semantic token taxonomy shared by every frontend? + R: no. Each frontend keeps its own vocabulary. +- [x] How should VS Code consume flexible frontend vocabularies without becoming the owner of semantic meaning? + R: through a frontend-authored host projection for VS Code. +- [x] Does this revise `DEC-0033`? + R: it complements `DEC-0033` by clarifying semantic vocabulary and host projection responsibilities. + +## Options + +### Option A - Canonicalize around VS Code token types + +- **Approach:** Force frontends to express semantic meaning in a shared VS Code-shaped taxonomy. +- **Pro:** Simplifies host adaptation. +- **Con:** Makes the host model canonical and removes frontend semantic freedom. +- **Maintainability:** Poor. It solves adapter simplicity by weakening frontend ownership. + +### Option B - Keep frontend vocabularies canonical and add declarative host projection + +- **Approach:** Let each frontend define its own semantic keys and publish host projection metadata that explains how a host such as VS Code should adapt those keys. +- **Pro:** Preserves frontend semantic ownership while keeping host adaptation mechanical. +- **Con:** Requires an additional contract layer. +- **Maintainability:** Strong. Ownership stays correct and adapters remain declarative. + +## Tradeoffs + +Option A would make the current VS Code situation easier, but only by moving semantic authorship to the wrong layer. + +Option B adds contract surface, but that surface is the correct one because it keeps the frontend canonical and makes host projection explicit rather than implicit. + +## Recommendation + +Adopt Option B. + +Frontend semantic keys remain canonical and flexible. +Hosts such as VS Code consume a declarative projection authored by the frontend for that host. + +## Discussion + +This discussion is intentionally narrow. +It does not reopen the frontend-owned visual theme decision. +It only clarifies that semantic vocabulary itself must also remain frontend-owned, and that host adaptation must be expressed as projection rather than normalization into a rigid shared taxonomy. + +## Resolution + +Accepted on 2026-05-06. + +Prometeu keeps frontend-owned semantic vocabularies flexible and introduces declarative host projection as the adaptation mechanism for hosts such as VS Code. diff --git a/discussion/workflow/decisions/DEC-0034-frontend-semantic-host-projection-flexibility.md b/discussion/workflow/decisions/DEC-0034-frontend-semantic-host-projection-flexibility.md new file mode 100644 index 00000000..7532a2d8 --- /dev/null +++ b/discussion/workflow/decisions/DEC-0034-frontend-semantic-host-projection-flexibility.md @@ -0,0 +1,112 @@ +--- +id: DEC-0034 +ticket: frontend-semantic-host-projection-flexibility +title: Frontend semantic vocabularies remain canonical and hosts consume declarative projections +status: accepted +created: 2026-05-06 +accepted: 2026-05-06 +agenda: AGD-0037 +plans: [PLN-0072, PLN-0073, PLN-0074] +tags: [compiler, compiler-general, frontend, semantics, vscode, host-projection, lsp] +--- + +## Decision + +Prometeu SHALL keep semantic vocabularies frontend-owned and canonical. +Hosts such as VS Code SHALL consume declarative host projection data authored by the frontend instead of forcing frontend semantic keys into a rigid shared host taxonomy. + +This decision locks the following normative points: + +1. Each frontend MUST remain free to define its own semantic keys. +2. Prometeu MUST NOT introduce a rigid global semantic token taxonomy as the canonical contract for all frontends. +3. Host-facing semantic adaptation MUST happen through frontend-authored host projection metadata. +4. Host projection metadata MUST be declarative and MUST NOT become the canonical semantic vocabulary. +5. VS Code adaptation MUST consume the frontend semantic vocabulary plus its VS Code projection, not reinterpret semantic meaning ad hoc inside the extension. + +## Rationale + +The current stack already establishes frontend ownership over visual themes. +Without this complementary rule, semantic vocabulary itself could still drift toward host ownership because VS Code prefers a different semantic model than a frontend may naturally publish. + +If the repository made VS Code token categories canonical, it would: + +1. collapse frontend semantic freedom, +2. move semantic authorship into the host layer, +3. and make frontend evolution hostage to one specific adapter model. + +Declarative host projection preserves the correct ownership boundary: + +1. frontend defines semantic meaning, +2. frontend also defines how a given host should project that meaning, +3. host adapters translate mechanically. + +## Technical Specification + +### 1. Canonical Semantic Vocabulary + +The canonical semantic vocabulary for a document language MUST live in that frontend's contract surface. + +This implies: + +1. semantic keys remain frontend-owned, +2. semantic keys MAY vary significantly between frontends, +3. semantic keys MUST NOT be rewritten into a mandatory repository-wide host-shaped taxonomy. + +### 2. Host Projection Contract + +Frontend metadata MUST evolve to support host projection descriptors. + +At minimum, a host projection descriptor for VS Code MUST be capable of expressing: + +1. which canonical semantic key is being projected, +2. which VS Code semantic token type should receive that key, +3. which VS Code semantic token modifiers, if any, should accompany that projection, +4. any fallback behavior needed when the host cannot represent the frontend key exactly. + +The host projection descriptor MAY support other hosts later, but the first required host projection is VS Code. + +### 3. Ownership Rules + +Ownership SHALL be: + +1. frontend owns semantic keys, +2. frontend owns host projection metadata, +3. LSP transports both, +4. the host adapter translates both. + +The extension MUST NOT become the place where semantic meaning is hand-mapped or reauthored as code-driven policy. + +### 4. Relationship to DEC-0033 + +This decision complements `DEC-0033`. + +`DEC-0033` remains normative for: + +1. frontend-owned visual theme contracts, +2. frontend-owned theme variants, +3. host adapter responsibilities for visual rendering. + +This decision adds the semantic vocabulary clarification that `DEC-0033` left implicit: + +1. semantic vocabularies remain frontend-owned and flexible, +2. host adaptation is projection, not normalization. + +### 5. VS Code Adapter Rule + +For VS Code specifically: + +1. the extension MUST consume frontend-owned semantic keys, +2. the extension MUST consume frontend-authored VS Code projection metadata, +3. the extension MUST apply that projection mechanically, +4. the extension MUST NOT force every frontend into a single rigid shared semantic taxonomy to satisfy VS Code. + +## Constraints + +1. No plan derived from this decision may replace frontend semantic keys with a mandatory global host taxonomy. +2. Any plan touching VS Code semantic adaptation MUST include declarative host projection support. +3. Any plan touching LSP transport for semantic vocabularies MUST preserve frontend canonical keys. +4. This decision MUST be treated as complementary to `DEC-0033`, not as a rollback of frontend-owned theming. + +## Revision Log + +- 2026-05-06: Initial accepted decision from AGD-0037. diff --git a/discussion/workflow/plans/PLN-0072-frontend-semantic-host-projection-contract.md b/discussion/workflow/plans/PLN-0072-frontend-semantic-host-projection-contract.md new file mode 100644 index 00000000..a4d829ee --- /dev/null +++ b/discussion/workflow/plans/PLN-0072-frontend-semantic-host-projection-contract.md @@ -0,0 +1,119 @@ +--- +id: PLN-0072 +ticket: frontend-semantic-host-projection-flexibility +title: Frontend Semantic Host Projection Contract +status: open +created: 2026-05-06 +completed: +tags: [compiler, compiler-general, frontend, semantics, host-projection, vscode, pbs] +--- + +## Objective + +Introduce the canonical frontend-authored semantic host projection contract in compiler-general frontend metadata and migrate PBS to publish its first VS Code projection without weakening frontend-owned semantic vocabulary. + +## Background + +`DEC-0034` locks that semantic vocabularies remain frontend-owned and canonical, while hosts such as VS Code consume declarative projection metadata authored by the frontend. The current semantic presentation work already establishes frontend-owned themes through `DEC-0033`, but semantic adaptation still lacks a structured host projection contract. + +PBS is the first concrete frontend and therefore the first migration target, but the contract MUST remain compiler-general rather than PBS-shaped. + +## Scope + +### Included +- Evolve compiler/frontend metadata to publish declarative semantic host projection descriptors. +- Define the contract shape for VS Code semantic token projection. +- Migrate PBS to author VS Code projection metadata for its canonical semantic keys. +- Add tests that lock the contract and prevent host-owned remapping logic from becoming the source of truth. + +### Excluded +- LSP transport changes. +- VS Code extension runtime consumption changes. +- Redesigning PBS canonical semantic keys to mimic VS Code categories. + +## Non-Goals + +- Introducing a global rigid semantic taxonomy across frontends. +- Making VS Code semantic token types the canonical frontend semantic contract. +- Solving projection for every future host in the first wave. + +## Execution Steps + +### Step 1 - Define compiler-general host projection metadata + +**What:** Extend the frontend semantic metadata surfaces to carry host projection descriptors alongside canonical semantic keys. +**How:** Add or evolve compiler-general model types so a frontend can declare, for each host projection entry: + +1. the canonical frontend semantic key being projected, +2. the target host identity, +3. the host token type or equivalent target category, +4. any host modifiers, +5. fallback projection semantics when the host cannot represent the key exactly. + +The contract MUST preserve the frontend semantic key as canonical and MUST treat projection as derivative metadata. +**File(s):** `prometeu-compiler/prometeu-compiler-core/src/main/java/p/studio/compiler/models/**`, related frontend definition surfaces. + +### Step 2 - Make projection rules operational and mechanically consumable + +**What:** Turn the projection contract into an exact operational surface rather than an informal note. +**How:** Define invariants, null/empty behavior, and lookup rules for projection descriptors, including: + +1. host identifier semantics, +2. duplicate or conflicting projection handling, +3. missing projection behavior, +4. fallback behavior representation, +5. safe access patterns from `FrontendSpec`. + +The result MUST allow host adapters to translate frontend-authored projection data mechanically without semantic reinterpretation. +**File(s):** `prometeu-compiler/prometeu-compiler-core/src/main/java/**`, associated compiler-general tests. + +### Step 3 - Migrate PBS to author its first VS Code projection + +**What:** Make PBS publish its VS Code semantic projection through the new contract. +**How:** Update PBS frontend metadata so its canonical semantic keys remain unchanged while the frontend also declares how each key projects into VS Code semantic token types and modifiers. The authored projection MUST live in PBS frontend metadata and MUST NOT be reauthored inside the extension. +**File(s):** `prometeu-compiler/frontends/prometeu-frontend-pbs/src/main/java/**`, related PBS semantic presentation tests. + +### Step 4 - Lock the contract with tests + +**What:** Prevent future drift toward host-owned semantic policy. +**How:** Add tests that assert: + +1. frontends publish projection descriptors through compiler-general metadata, +2. PBS canonical keys remain frontend-owned, +3. PBS VS Code projection resolves mechanically from frontend metadata, +4. no global repository-wide rigid semantic taxonomy is introduced as the canonical contract. + +**File(s):** compiler-general and PBS test suites. + +## Test Requirements + +### Unit Tests +- Validate projection model invariants, including required frontend key linkage and host target fields. +- Validate `FrontendSpec` safely exposes host projection metadata. +- Validate missing and duplicate projection handling. + +### Integration Tests +- Run targeted compiler and PBS tests proving host projection metadata compiles, resolves, and remains discoverable through frontend definitions. + +### Manual Verification +- Inspect PBS frontend metadata and confirm the VS Code projection is authored there rather than in host adapter code. +- Confirm canonical PBS semantic keys remain readable and unchanged in ownership terms. + +## Acceptance Criteria + +- [ ] Compiler-general frontend metadata publishes declarative host projection descriptors. +- [ ] The contract preserves canonical frontend semantic keys as the source of truth. +- [ ] The contract supports a VS Code projection without forcing a global rigid taxonomy. +- [ ] PBS authors its VS Code semantic projection through the new contract. +- [ ] Tests lock the contract against host-owned semantic remapping drift. + +## Dependencies + +- `DEC-0034` accepted and normatively locked. +- `DEC-0033` accepted where semantic presentation metadata already exists and may need coordinated evolution. + +## Risks + +- Overfitting projection fields to PBS or to VS Code would weaken future frontend flexibility. +- Allowing ambiguous projection semantics would push semantic authorship back into adapters. +- Collapsing canonical keys into host-shaped aliases would violate `DEC-0034`. diff --git a/discussion/workflow/plans/PLN-0073-lsp-semantic-host-projection-transport.md b/discussion/workflow/plans/PLN-0073-lsp-semantic-host-projection-transport.md new file mode 100644 index 00000000..3c7ea505 --- /dev/null +++ b/discussion/workflow/plans/PLN-0073-lsp-semantic-host-projection-transport.md @@ -0,0 +1,107 @@ +--- +id: PLN-0073 +ticket: frontend-semantic-host-projection-flexibility +title: LSP Semantic Host Projection Transport +status: open +created: 2026-05-06 +completed: +tags: [lsp, compiler, frontend, semantics, host-projection, vscode, protocol] +--- + +## Objective + +Transport canonical frontend semantic vocabulary and frontend-authored VS Code host projection metadata through the Prometeu LSP boundary without normalizing semantic meaning inside the transport layer. + +## Background + +`DEC-0034` requires LSP to carry both canonical frontend semantic keys and frontend-authored host projection metadata, while preserving the ownership boundary between frontend semantics and host adaptation. `DEC-0033` already introduced frontend-authored visual themes through the LSP handshake; semantic host projection must now follow the same ownership model. + +## Scope + +### Included +- Extend LSP-facing baseline message models to carry semantic host projection metadata. +- Update the compiler-backed language service bridge to resolve and expose that metadata from frontend definitions. +- Update the LSP protocol mapper to publish the transported metadata to the VS Code extension. +- Add tests that prove canonical keys and projection metadata are both preserved across transport. + +### Excluded +- Defining the compiler-general projection contract itself. +- Applying the projection inside the VS Code extension. +- Redesigning semantic token classification logic beyond what is needed to expose projection metadata. + +## Non-Goals + +- Performing semantic normalization inside the LSP layer. +- Collapsing frontend semantic keys into host token types in baseline message models. +- Introducing host-specific semantic rules into `lsp-api` that belong to frontend metadata. + +## Execution Steps + +### Step 1 - Extend baseline transport models for semantic projection + +**What:** Add baseline message shapes that can carry semantic host projection metadata. +**How:** Evolve LSP-facing DTOs so the server description or related handshake payload can transport: + +1. frontend language identity, +2. canonical frontend semantic keys, +3. one or more host projection entries for VS Code, +4. any fallback metadata required by the projection contract. + +The transport model MUST preserve canonical frontend keys explicitly rather than flattening everything into host token types. +**File(s):** `prometeu-lsp/prometeu-lsp-api/src/main/java/**`, `prometeu-lsp/prometeu-lsp-v1/src/main/java/p/studio/lsp/messages/**`. + +### Step 2 - Resolve transport payload from compiler frontend metadata + +**What:** Make the language service bridge expose semantic host projection metadata from the frontend contract. +**How:** Update compiler-backed bridge code to read canonical semantic keys plus VS Code projection descriptors from the frontend definition and map them into the baseline transport payload without reinterpreting semantic meaning. +**File(s):** `prometeu-lsp/prometeu-lsp-v1/src/main/java/p/studio/lsp/services/compiler/**`. + +### Step 3 - Publish the projection payload through the handshake + +**What:** Make the VS Code client able to receive semantic projection metadata at initialization time. +**How:** Update the protocol mapping layer so the initialize result transports canonical semantic keys and VS Code projection metadata through the agreed experimental surface or another current handshake surface, while keeping semantic theming transport from `DEC-0033` intact and coherent. +**File(s):** `prometeu-lsp/prometeu-lsp-v1/src/main/java/p/studio/lsp/services/protocol/mapping/**`, related server description surfaces. + +### Step 4 - Lock transport behavior with tests + +**What:** Prevent future drift toward semantic normalization inside LSP. +**How:** Add tests that assert: + +1. canonical frontend semantic keys survive transport, +2. VS Code projection entries survive transport, +3. payload structure remains mechanically consumable by the extension, +4. the transport layer does not replace frontend keys with host token categories. + +**File(s):** `prometeu-lsp/prometeu-lsp-v1/src/test/java/**`, `prometeu-lsp/prometeu-lsp-api` tests if present. + +## Test Requirements + +### Unit Tests +- Validate mapping from frontend projection metadata into baseline transport DTOs. +- Validate transport serialization of canonical keys plus projection entries. + +### Integration Tests +- Run targeted `lsp-v1` tests proving the server handshake exposes both semantic themes and semantic host projection coherently. + +### Manual Verification +- Inspect the initialize payload and confirm that frontend semantic keys and VS Code projection metadata are both visible. +- Confirm no layer in LSP rewrites canonical semantic keys into a mandatory host taxonomy. + +## Acceptance Criteria + +- [ ] LSP transport models carry canonical frontend semantic keys and VS Code projection metadata together. +- [ ] The compiler-backed bridge resolves that metadata directly from frontend definitions. +- [ ] The initialize payload exposes the metadata mechanically to the extension. +- [ ] Tests lock the transport layer against semantic normalization drift. + +## Dependencies + +- `DEC-0034` accepted and normatively locked. +- `PLN-0072` completes the compiler/frontend projection contract. +- `DEC-0033` transport conventions remain in force for visual theme payloads. + +## Risks + +- Reusing visual theme payload structures carelessly could blur the boundary between visual and semantic contracts. +- Flattening transport too aggressively could erase canonical frontend key identity. +- Excessive protocol specialization could make future hosts harder to add. diff --git a/discussion/workflow/plans/PLN-0074-vscode-semantic-host-projection-adapter.md b/discussion/workflow/plans/PLN-0074-vscode-semantic-host-projection-adapter.md new file mode 100644 index 00000000..eab87eec --- /dev/null +++ b/discussion/workflow/plans/PLN-0074-vscode-semantic-host-projection-adapter.md @@ -0,0 +1,109 @@ +--- +id: PLN-0074 +ticket: frontend-semantic-host-projection-flexibility +title: VS Code Semantic Host Projection Adapter +status: open +created: 2026-05-06 +completed: +tags: [vscode, extension, frontend, semantics, host-projection, adapter] +--- + +## Objective + +Make the VS Code extension consume frontend-authored semantic host projection metadata mechanically so semantic highlighting behavior no longer depends on extension-owned assumptions about frontend semantic key names. + +## Background + +`DEC-0034` makes the frontend semantic vocabulary canonical and requires VS Code adaptation to follow frontend-authored projection metadata rather than an extension-owned taxonomy. `DEC-0033` already moved visual theme ownership into frontend-authored runtime payloads; the semantic adapter must now follow the same model. + +The current extension still contains assumptions about semantic token naming and package-level declarations that do not fully reflect frontend-authored projection data. + +## Scope + +### Included +- Consume semantic host projection payload from the LSP handshake. +- Translate frontend-authored VS Code projection descriptors into the extension's semantic token registration and runtime theme application flow. +- Reduce extension-owned semantic assumptions to the minimum static structure the VS Code platform requires. +- Add tests or verification hooks that prove the adapter follows frontend-authored projection data mechanically. + +### Excluded +- Inventing or redefining canonical semantic meaning inside the extension. +- Reworking compiler semantic classification beyond consuming the delivered keys and projections. +- Solving projection for non-VS Code hosts. + +## Non-Goals + +- Making the extension the owner of semantic taxonomy policy. +- Hardcoding PBS-specific semantic mapping logic as the authoritative source. +- Guaranteeing a perfect one-to-one rendering match with Studio for every frontend key. + +## Execution Steps + +### Step 1 - Update extension-side semantic projection models + +**What:** Add extension-side runtime shapes for the transported semantic projection payload. +**How:** Extend the VS Code extension client code so it can read and store: + +1. canonical frontend semantic keys, +2. VS Code projection entries per key, +3. fallback metadata if present, +4. any language-scoped identity needed to apply the projection safely. + +These runtime shapes MUST reflect transported frontend-authored metadata rather than a hand-maintained extension mapping table. +**File(s):** `tools/vscode-extension/src/**`, generated `out/**` mirror as needed. + +### Step 2 - Apply projection mechanically in the semantic adapter path + +**What:** Make the extension derive VS Code-facing semantic behavior from the transported projection. +**How:** Update extension logic so semantic token registration, selectors, and any runtime semantic color rule generation consume the frontend-authored projection entries. The adapter MUST treat missing projection data as a fallback condition, not as permission to reauthor semantic meaning broadly in extension code. +**File(s):** `tools/vscode-extension/src/extension.ts`, related extension helper modules if introduced, generated `out/**` mirror as needed. + +### Step 3 - Minimize static package-level semantic assumptions + +**What:** Reduce static `package.json` semantic declarations to the minimum platform-required scaffolding. +**How:** Audit the extension manifest and runtime so static declarations remain only where VS Code requires them structurally. Any semantic mapping policy that can be expressed by frontend-authored projection data MUST move out of the manifest and into runtime translation logic. +**File(s):** `tools/vscode-extension/package.json`, `tools/vscode-extension/src/**`. + +### Step 4 - Lock adapter behavior with tests and verification + +**What:** Prevent regression toward extension-owned semantic policy. +**How:** Add tests or targeted verification code that assert: + +1. the adapter reads frontend-authored projection payloads, +2. semantic rules derive from projection data rather than hardcoded PBS assumptions, +3. fallback paths stay bounded and explicit, +4. frontend projection updates do not require extension semantic remapping edits for ordinary token adjustments. + +**File(s):** extension test surfaces if present, otherwise targeted runtime assertions and documented manual verification paths. + +## Test Requirements + +### Unit Tests +- Validate parsing of semantic projection payloads from the initialize response. +- Validate transformation from projection entries into VS Code semantic token rule inputs. + +### Integration Tests +- If extension test infrastructure exists, verify that a mock initialize payload drives semantic adapter behavior without code-level remapping tables. + +### Manual Verification +- Reload the extension and inspect runtime behavior with a PBS project to confirm semantic highlighting is driven by transported projection data. +- Confirm that a frontend-authored projection change would only require frontend/LSP updates, not new semantic mapping logic in the extension. + +## Acceptance Criteria + +- [ ] The extension consumes canonical semantic keys and VS Code projection metadata from the LSP handshake. +- [ ] Semantic adapter behavior derives mechanically from transported projection data. +- [ ] Static extension manifest assumptions are reduced to platform-required scaffolding. +- [ ] The extension no longer acts as the authoritative source of frontend semantic mapping policy. + +## Dependencies + +- `DEC-0034` accepted and normatively locked. +- `PLN-0073` completes LSP transport of semantic host projection metadata. +- `DEC-0033` dynamic visual theme translation remains in place and coherent with semantic adaptation. + +## Risks + +- VS Code manifest constraints may still require some static declarations, and those boundaries must stay explicit. +- Weak fallback rules could accidentally recreate extension-owned semantic policy. +- Failure to update generated extension output alongside source would leave the runtime out of sync in the current local environment. diff --git a/prometeu-compiler/frontends/prometeu-frontend-pbs/src/main/java/p/studio/compiler/PBSDefinitions.java b/prometeu-compiler/frontends/prometeu-frontend-pbs/src/main/java/p/studio/compiler/PBSDefinitions.java index 28ea25d7..3c899177 100644 --- a/prometeu-compiler/frontends/prometeu-frontend-pbs/src/main/java/p/studio/compiler/PBSDefinitions.java +++ b/prometeu-compiler/frontends/prometeu-frontend-pbs/src/main/java/p/studio/compiler/PBSDefinitions.java @@ -1,10 +1,7 @@ package p.studio.compiler; -import p.studio.compiler.models.FrontendSpec; -import p.studio.compiler.models.FrontendEditorPaletteSpec; import p.studio.compiler.models.FrontendSemanticPresentationSpec; -import p.studio.compiler.models.FrontendTokenStyleSpec; -import p.studio.compiler.models.FrontendVisualThemeSpec; +import p.studio.compiler.models.FrontendSpec; import p.studio.compiler.pbs.PbsSemanticKind; import p.studio.utilities.structures.ReadOnlySet; @@ -19,41 +16,7 @@ public class PBSDefinitions { .stdlibVersions(List.of(FrontendSpec.Stdlib.asDefault(1))) .semanticPresentation(new FrontendSemanticPresentationSpec( PbsSemanticKind.semanticKeys(), - List.of(new FrontendVisualThemeSpec( - "pbs-default", - "PBS Default", - new FrontendEditorPaletteSpec( - "#d9e2ec", - "#2d4f6b", - "#2d4f6b", - "#6f8193", - "#2c2140", - "#a47dff", - "#efe6ff"), - List.of( - new FrontendTokenStyleSpec("pbs-comment", "#c090b0", true, false, false), - new FrontendTokenStyleSpec("pbs-string", "#00c088", false, false, false), - new FrontendTokenStyleSpec("pbs-number", "#ff90b0", false, false, false), - new FrontendTokenStyleSpec("pbs-literal", "#4fc1ff", false, false, false), - new FrontendTokenStyleSpec("pbs-lifecycle", "#ef50c0", false, false, false), - new FrontendTokenStyleSpec("pbs-keyword", "#569cd6", false, false, false), - new FrontendTokenStyleSpec("pbs-operator", "#d4d4d4", false, false, false), - new FrontendTokenStyleSpec("pbs-punctuation", "#d4d4d4", false, false, false), - new FrontendTokenStyleSpec("pbs-function", "#f2c14e", false, false, false), - new FrontendTokenStyleSpec("pbs-method", "#f2c14e", false, false, false), - new FrontendTokenStyleSpec("pbs-constructor", "#ecdcaa", false, false, false), - new FrontendTokenStyleSpec("pbs-struct", "#4ec9b0", false, false, false), - new FrontendTokenStyleSpec("pbs-contract", "#78dce8", false, false, false), - new FrontendTokenStyleSpec("pbs-host", "#b7a2fa", false, false, false), - new FrontendTokenStyleSpec("pbs-builtin-type", "#8be9fd", false, false, false), - new FrontendTokenStyleSpec("pbs-service", "#b7a2fa", false, false, false), - new FrontendTokenStyleSpec("pbs-error", "#ff5b5b", false, false, false), - new FrontendTokenStyleSpec("pbs-enum", "#56cfe1", false, false, false), - new FrontendTokenStyleSpec("pbs-callback", "#b7a2fa", false, false, false), - new FrontendTokenStyleSpec("pbs-global", "#f790fc", true, false, false), - new FrontendTokenStyleSpec("pbs-const", "#f78c6c", false, false, false), - new FrontendTokenStyleSpec("pbs-implements", "#a1c181", false, false, false), - new FrontendTokenStyleSpec("pbs-identifier", "#d4d4d4", false, false, false)))), + List.of(PBSFrontendThemes.DEFAULT_PBS), "pbs-default")) .build(); } diff --git a/prometeu-compiler/frontends/prometeu-frontend-pbs/src/main/java/p/studio/compiler/PBSFrontendThemes.java b/prometeu-compiler/frontends/prometeu-frontend-pbs/src/main/java/p/studio/compiler/PBSFrontendThemes.java new file mode 100644 index 00000000..492d342c --- /dev/null +++ b/prometeu-compiler/frontends/prometeu-frontend-pbs/src/main/java/p/studio/compiler/PBSFrontendThemes.java @@ -0,0 +1,45 @@ +package p.studio.compiler; + +import p.studio.compiler.models.FrontendEditorPaletteSpec; +import p.studio.compiler.models.FrontendTokenStyleSpec; +import p.studio.compiler.models.FrontendVisualThemeSpec; + +import java.util.List; + +public class PBSFrontendThemes { + public static final FrontendVisualThemeSpec DEFAULT_PBS = new FrontendVisualThemeSpec( + "pbs-default", + "PBS Default", + new FrontendEditorPaletteSpec( + "#d9e2ec", + "#2d4f6b", + "#2d4f6b", + "#6f8193", + "#2c2140", + "#a47dff", + "#efe6ff"), + List.of( + new FrontendTokenStyleSpec("pbs-comment", "#c090b0", true, false, false), + new FrontendTokenStyleSpec("pbs-string", "#00c088", false, false, false), + new FrontendTokenStyleSpec("pbs-number", "#ff90b0", false, false, false), + new FrontendTokenStyleSpec("pbs-literal", "#4fc1ff", false, false, false), + new FrontendTokenStyleSpec("pbs-lifecycle", "#ef50c0", false, false, false), + new FrontendTokenStyleSpec("pbs-keyword", "#569cd6", false, false, false), + new FrontendTokenStyleSpec("pbs-operator", "#d4d4d4", false, false, false), + new FrontendTokenStyleSpec("pbs-punctuation", "#d4d4d4", false, false, false), + new FrontendTokenStyleSpec("pbs-function", "#f2c14e", false, false, false), + new FrontendTokenStyleSpec("pbs-method", "#f2c14e", false, false, false), + new FrontendTokenStyleSpec("pbs-constructor", "#ecdcaa", false, false, false), + new FrontendTokenStyleSpec("pbs-struct", "#4ec9b0", false, false, false), + new FrontendTokenStyleSpec("pbs-contract", "#78dce8", false, false, false), + new FrontendTokenStyleSpec("pbs-host", "#b7a2fa", false, false, false), + new FrontendTokenStyleSpec("pbs-builtin-type", "#8be9fd", false, false, false), + new FrontendTokenStyleSpec("pbs-service", "#b7a2fa", false, false, false), + new FrontendTokenStyleSpec("pbs-error", "#ff5b5b", false, false, false), + new FrontendTokenStyleSpec("pbs-enum", "#56cfe1", false, false, false), + new FrontendTokenStyleSpec("pbs-callback", "#b7a2fa", false, false, false), + new FrontendTokenStyleSpec("pbs-global", "#f790fc", true, false, false), + new FrontendTokenStyleSpec("pbs-const", "#f78c6c", false, false, false), + new FrontendTokenStyleSpec("pbs-implements", "#a1c181", false, false, false), + new FrontendTokenStyleSpec("pbs-identifier", "#d4d4d4", false, false, false))); +} diff --git a/test-projects/main/.vscode/settings.json b/test-projects/main/.vscode/settings.json new file mode 100644 index 00000000..1bc56666 --- /dev/null +++ b/test-projects/main/.vscode/settings.json @@ -0,0 +1,41 @@ +{ + "editor.semanticTokenColorCustomizations": { + "enabled": true, + "rules": { + "pbs-comment:pbs": { + "foreground": "#c090b0", + "italic": true + }, + "pbs-string:pbs": "#00c088", + "pbs-number:pbs": "#ff90b0", + "pbs-literal:pbs": "#4fc1ff", + "pbs-lifecycle:pbs": "#ef50c0", + "pbs-keyword:pbs": "#569cd6", + "pbs-operator:pbs": "#d4d4d4", + "pbs-punctuation:pbs": "#d4d4d4", + "pbs-function:pbs": "#f2c14e", + "pbs-method:pbs": "#f2c14e", + "pbs-constructor:pbs": "#ecdcaa", + "pbs-struct:pbs": "#4ec9b0", + "pbs-contract:pbs": "#78dce8", + "pbs-host:pbs": "#b7a2fa", + "pbs-builtin-type:pbs": "#8be9fd", + "pbs-service:pbs": "#b7a2fa", + "pbs-error:pbs": "#ff5b5b", + "pbs-enum:pbs": "#56cfe1", + "pbs-callback:pbs": "#b7a2fa", + "pbs-global:pbs": { + "foreground": "#f790fc", + "italic": true + }, + "pbs-const:pbs": "#f78c6c", + "pbs-implements:pbs": "#a1c181", + "pbs-identifier:pbs": "#d4d4d4" + } + }, + "workbench.colorCustomizations": { + "editor.foreground": "#d9e2ec", + "editor.selectionBackground": "#2d4f6b", + "editorLineNumber.foreground": "#6f8193" + } +} \ No newline at end of file diff --git a/tools/vscode-extension/out/extension.js b/tools/vscode-extension/out/extension.js index bd27beb0..6e850aff 100644 --- a/tools/vscode-extension/out/extension.js +++ b/tools/vscode-extension/out/extension.js @@ -289,4 +289,4 @@ function readObject(value) { } return value; } -//# sourceMappingURL=extension.js.map +//# sourceMappingURL=extension.js.map \ No newline at end of file -- 2.47.2 From 9d75f2f0e29a4795d31b8a9a5d631cd79394312f Mon Sep 17 00:00:00 2001 From: bQUARKz Date: Wed, 6 May 2026 15:24:21 +0100 Subject: [PATCH 23/37] implements PLN-0072 --- discussion/index.ndjson | 2 +- ...ntend-semantic-host-projection-contract.md | 4 +- .../p/studio/compiler/PBSDefinitions.java | 3 +- .../compiler/PBSFrontendHostProjections.java | 97 +++++++++++++++++++ .../PbsSemanticPresentationContractTest.java | 17 ++++ .../FrontendHostProjectionEntrySpec.java | 38 ++++++++ .../models/FrontendHostProjectionSpec.java | 48 +++++++++ .../FrontendSemanticPresentationSpec.java | 43 +++++++- .../FrontendSemanticPresentationSpecTest.java | 85 ++++++++++++++++ 9 files changed, 330 insertions(+), 7 deletions(-) create mode 100644 prometeu-compiler/frontends/prometeu-frontend-pbs/src/main/java/p/studio/compiler/PBSFrontendHostProjections.java create mode 100644 prometeu-compiler/prometeu-compiler-core/src/main/java/p/studio/compiler/models/FrontendHostProjectionEntrySpec.java create mode 100644 prometeu-compiler/prometeu-compiler-core/src/main/java/p/studio/compiler/models/FrontendHostProjectionSpec.java create mode 100644 prometeu-compiler/prometeu-compiler-core/src/test/java/p/studio/compiler/models/FrontendSemanticPresentationSpecTest.java diff --git a/discussion/index.ndjson b/discussion/index.ndjson index 4369e623..17cc4fc5 100644 --- a/discussion/index.ndjson +++ b/discussion/index.ndjson @@ -1,5 +1,5 @@ {"type":"meta","next_id":{"DSC":35,"AGD":38,"DEC":35,"PLN":75,"LSN":47,"CLSN":1}} -{"type":"discussion","id":"DSC-0034","status":"in_progress","ticket":"frontend-semantic-host-projection-flexibility","title":"Frontend semantic vocabulary flexibility and declarative host projection","created_at":"2026-05-06","updated_at":"2026-05-06","tags":["compiler","compiler-general","frontend","semantics","vscode","host-projection","lsp"],"agendas":[{"id":"AGD-0037","file":"AGD-0037-frontend-semantic-host-projection-flexibility.md","status":"accepted","created_at":"2026-05-06","updated_at":"2026-05-06"}],"decisions":[{"id":"DEC-0034","file":"DEC-0034-frontend-semantic-host-projection-flexibility.md","status":"accepted","created_at":"2026-05-06","updated_at":"2026-05-06","ref_agenda":"AGD-0037"}],"plans":[{"id":"PLN-0072","file":"PLN-0072-frontend-semantic-host-projection-contract.md","status":"open","created_at":"2026-05-06","updated_at":"2026-05-06","ref_decisions":["DEC-0034"]},{"id":"PLN-0073","file":"PLN-0073-lsp-semantic-host-projection-transport.md","status":"open","created_at":"2026-05-06","updated_at":"2026-05-06","ref_decisions":["DEC-0034"]},{"id":"PLN-0074","file":"PLN-0074-vscode-semantic-host-projection-adapter.md","status":"open","created_at":"2026-05-06","updated_at":"2026-05-06","ref_decisions":["DEC-0034"]}],"lessons":[]} +{"type":"discussion","id":"DSC-0034","status":"in_progress","ticket":"frontend-semantic-host-projection-flexibility","title":"Frontend semantic vocabulary flexibility and declarative host projection","created_at":"2026-05-06","updated_at":"2026-05-06","tags":["compiler","compiler-general","frontend","semantics","vscode","host-projection","lsp"],"agendas":[{"id":"AGD-0037","file":"AGD-0037-frontend-semantic-host-projection-flexibility.md","status":"accepted","created_at":"2026-05-06","updated_at":"2026-05-06"}],"decisions":[{"id":"DEC-0034","file":"DEC-0034-frontend-semantic-host-projection-flexibility.md","status":"accepted","created_at":"2026-05-06","updated_at":"2026-05-06","ref_agenda":"AGD-0037"}],"plans":[{"id":"PLN-0072","file":"PLN-0072-frontend-semantic-host-projection-contract.md","status":"done","created_at":"2026-05-06","updated_at":"2026-05-06","ref_decisions":["DEC-0034"]},{"id":"PLN-0073","file":"PLN-0073-lsp-semantic-host-projection-transport.md","status":"open","created_at":"2026-05-06","updated_at":"2026-05-06","ref_decisions":["DEC-0034"]},{"id":"PLN-0074","file":"PLN-0074-vscode-semantic-host-projection-adapter.md","status":"open","created_at":"2026-05-06","updated_at":"2026-05-06","ref_decisions":["DEC-0034"]}],"lessons":[]} {"type":"discussion","id":"DSC-0033","status":"in_progress","ticket":"frontend-visual-theme-spec-and-css-retirement","title":"Frontend visual theme spec and retirement of host-consumed semantic CSS","created_at":"2026-05-06","updated_at":"2026-05-06","tags":["compiler","compiler-general","frontend","presentation","theming","studio","vscode","lsp","pbs"],"agendas":[{"id":"AGD-0036","file":"AGD-0036-frontend-visual-theme-spec-and-css-retirement.md","status":"accepted","created_at":"2026-05-06","updated_at":"2026-05-06"}],"decisions":[{"id":"DEC-0033","file":"DEC-0033-frontend-visual-theme-spec-and-css-retirement.md","status":"accepted","created_at":"2026-05-06","updated_at":"2026-05-06","ref_agenda":"AGD-0036"}],"plans":[{"id":"PLN-0068","file":"PLN-0068-frontend-visual-contract-and-pbs-migration.md","status":"open","created_at":"2026-05-06","updated_at":"2026-05-06","ref_decisions":["DEC-0033"]},{"id":"PLN-0069","file":"PLN-0069-lsp-visual-theme-transport-and-selection.md","status":"open","created_at":"2026-05-06","updated_at":"2026-05-06","ref_decisions":["DEC-0033"]},{"id":"PLN-0070","file":"PLN-0070-studio-visual-theme-adapter-and-css-retirement.md","status":"open","created_at":"2026-05-06","updated_at":"2026-05-06","ref_decisions":["DEC-0033"]},{"id":"PLN-0071","file":"PLN-0071-vscode-dynamic-theme-translation-adapter.md","status":"open","created_at":"2026-05-06","updated_at":"2026-05-06","ref_decisions":["DEC-0033"]}],"lessons":[]} {"type":"discussion","id":"DSC-0032","status":"in_progress","ticket":"studio-new-lsp-api-and-v1-boundary","title":"Novo boundary entre lsp-api, lsp-v1 e a extensao VS Code","created_at":"2026-05-05","updated_at":"2026-05-05","tags":["studio","lsp","vscode","protocol","api","boundary"],"agendas":[{"id":"AGD-0035","file":"AGD-0035-studio-new-lsp-api-and-v1-boundary.md","status":"accepted","created_at":"2026-05-05","updated_at":"2026-05-05"}],"decisions":[{"id":"DEC-0032","file":"DEC-0032-studio-new-lsp-api-and-v1-boundary.md","status":"accepted","created_at":"2026-05-05","updated_at":"2026-05-05","ref_agenda":"AGD-0035"}],"plans":[{"id":"PLN-0065","file":"PLN-0065-lsp-boundary-and-module-scaffolding.md","status":"done","created_at":"2026-05-05","updated_at":"2026-05-05","ref_decisions":["DEC-0032"]},{"id":"PLN-0066","file":"PLN-0066-project-scoped-lsp-server-lifecycle-in-studio.md","status":"done","created_at":"2026-05-05","updated_at":"2026-05-05","ref_decisions":["DEC-0032"]},{"id":"PLN-0067","file":"PLN-0067-compiler-backed-dumb-lsp-server-baseline.md","status":"done","created_at":"2026-05-05","updated_at":"2026-05-05","ref_decisions":["DEC-0032"]}],"lessons":[]} {"type":"discussion","id":"DSC-0031","status":"in_progress","ticket":"studio-editor-workspace-cleanup","title":"Limpeza completa do Workspace Editor do Studio e remoção dos acoplamentos legados","created_at":"2026-05-05","updated_at":"2026-05-05","tags":["studio","editor","cleanup","vfs","lsp","migration"],"agendas":[{"id":"AGD-0034","file":"AGD-0034-vscode-editor-migration-feasibility.md","status":"accepted","created_at":"2026-05-05","updated_at":"2026-05-05"}],"decisions":[{"id":"DEC-0031","file":"DEC-0031-studio-editor-workspace-cleanup.md","status":"in_progress","created_at":"2026-05-05","updated_at":"2026-05-05","ref_agenda":"AGD-0034"}],"plans":[{"id":"PLN-0062","file":"PLN-0062-shell-session-and-state-cleanup-after-editor-removal.md","status":"done","created_at":"2026-05-05","updated_at":"2026-05-05","ref_decisions":["DEC-0031"]},{"id":"PLN-0063","file":"PLN-0063-legacy-lsp-and-vfs-module-removal-with-runtime-preservation.md","status":"done","created_at":"2026-05-05","updated_at":"2026-05-05","ref_decisions":["DEC-0031"]},{"id":"PLN-0064","file":"PLN-0064-normative-test-and-lesson-cleanup-for-editor-stack-removal.md","status":"done","created_at":"2026-05-05","updated_at":"2026-05-05","ref_decisions":["DEC-0031"]}],"lessons":[]} diff --git a/discussion/workflow/plans/PLN-0072-frontend-semantic-host-projection-contract.md b/discussion/workflow/plans/PLN-0072-frontend-semantic-host-projection-contract.md index a4d829ee..cd4ed79a 100644 --- a/discussion/workflow/plans/PLN-0072-frontend-semantic-host-projection-contract.md +++ b/discussion/workflow/plans/PLN-0072-frontend-semantic-host-projection-contract.md @@ -2,9 +2,9 @@ id: PLN-0072 ticket: frontend-semantic-host-projection-flexibility title: Frontend Semantic Host Projection Contract -status: open +status: done created: 2026-05-06 -completed: +completed: 2026-05-06 tags: [compiler, compiler-general, frontend, semantics, host-projection, vscode, pbs] --- diff --git a/prometeu-compiler/frontends/prometeu-frontend-pbs/src/main/java/p/studio/compiler/PBSDefinitions.java b/prometeu-compiler/frontends/prometeu-frontend-pbs/src/main/java/p/studio/compiler/PBSDefinitions.java index 3c899177..4daf9129 100644 --- a/prometeu-compiler/frontends/prometeu-frontend-pbs/src/main/java/p/studio/compiler/PBSDefinitions.java +++ b/prometeu-compiler/frontends/prometeu-frontend-pbs/src/main/java/p/studio/compiler/PBSDefinitions.java @@ -17,6 +17,7 @@ public class PBSDefinitions { .semanticPresentation(new FrontendSemanticPresentationSpec( PbsSemanticKind.semanticKeys(), List.of(PBSFrontendThemes.DEFAULT_PBS), - "pbs-default")) + "pbs-default", + List.of(PBSFrontendHostProjections.VSCODE))) .build(); } diff --git a/prometeu-compiler/frontends/prometeu-frontend-pbs/src/main/java/p/studio/compiler/PBSFrontendHostProjections.java b/prometeu-compiler/frontends/prometeu-frontend-pbs/src/main/java/p/studio/compiler/PBSFrontendHostProjections.java new file mode 100644 index 00000000..995bfeac --- /dev/null +++ b/prometeu-compiler/frontends/prometeu-frontend-pbs/src/main/java/p/studio/compiler/PBSFrontendHostProjections.java @@ -0,0 +1,97 @@ +package p.studio.compiler; + +import p.studio.compiler.models.FrontendHostProjectionEntrySpec; +import p.studio.compiler.models.FrontendHostProjectionSpec; + +import java.util.Arrays; + +import static p.studio.compiler.pbs.PbsSemanticKind.BUILTIN_TYPE; +import static p.studio.compiler.pbs.PbsSemanticKind.CALLBACK; +import static p.studio.compiler.pbs.PbsSemanticKind.COMMENT; +import static p.studio.compiler.pbs.PbsSemanticKind.CONST; +import static p.studio.compiler.pbs.PbsSemanticKind.CONSTRUCTOR; +import static p.studio.compiler.pbs.PbsSemanticKind.CONTRACT; +import static p.studio.compiler.pbs.PbsSemanticKind.ENUM; +import static p.studio.compiler.pbs.PbsSemanticKind.ERROR; +import static p.studio.compiler.pbs.PbsSemanticKind.FUNCTION; +import static p.studio.compiler.pbs.PbsSemanticKind.GLOBAL; +import static p.studio.compiler.pbs.PbsSemanticKind.HOST; +import static p.studio.compiler.pbs.PbsSemanticKind.IDENTIFIER; +import static p.studio.compiler.pbs.PbsSemanticKind.IMPLEMENTS; +import static p.studio.compiler.pbs.PbsSemanticKind.KEYWORD; +import static p.studio.compiler.pbs.PbsSemanticKind.LIFECYCLE; +import static p.studio.compiler.pbs.PbsSemanticKind.LITERAL; +import static p.studio.compiler.pbs.PbsSemanticKind.METHOD; +import static p.studio.compiler.pbs.PbsSemanticKind.NUMBER; +import static p.studio.compiler.pbs.PbsSemanticKind.OPERATOR; +import static p.studio.compiler.pbs.PbsSemanticKind.PUNCTUATION; +import static p.studio.compiler.pbs.PbsSemanticKind.SERVICE; +import static p.studio.compiler.pbs.PbsSemanticKind.STRING; +import static p.studio.compiler.pbs.PbsSemanticKind.STRUCT; + +public final class PBSFrontendHostProjections { + public static final String VSCODE_HOST_ID = "vscode"; + + public static final FrontendHostProjectionSpec VSCODE = new FrontendHostProjectionSpec( + VSCODE_HOST_ID, + Arrays.stream(p.studio.compiler.pbs.PbsSemanticKind.values()) + .map(PBSFrontendHostProjections::mapVscodeProjection) + .toList()); + + private PBSFrontendHostProjections() { + } + + private static FrontendHostProjectionEntrySpec mapVscodeProjection(final p.studio.compiler.pbs.PbsSemanticKind kind) { + return switch (kind) { + case COMMENT -> projection(COMMENT.semanticKey(), "comment"); + case STRING -> projection(STRING.semanticKey(), "string"); + case NUMBER -> projection(NUMBER.semanticKey(), "number"); + case LITERAL -> projection(LITERAL.semanticKey(), "enumMember", "variable"); + case LIFECYCLE -> projection(LIFECYCLE.semanticKey(), "function", "variable", "async"); + case KEYWORD -> projection(KEYWORD.semanticKey(), "keyword"); + case OPERATOR -> projection(OPERATOR.semanticKey(), "operator", "keyword"); + case PUNCTUATION -> projection(PUNCTUATION.semanticKey(), "operator", "keyword"); + case FUNCTION -> projection(FUNCTION.semanticKey(), "function"); + case METHOD -> projection(METHOD.semanticKey(), "method", "function"); + case CONSTRUCTOR -> projection(CONSTRUCTOR.semanticKey(), "class", "type", "declaration"); + case STRUCT -> projection(STRUCT.semanticKey(), "struct", "type"); + case CONTRACT -> projection(CONTRACT.semanticKey(), "interface", "type"); + case HOST -> projection(HOST.semanticKey(), "class", "type", "defaultLibrary"); + case BUILTIN_TYPE -> projection(BUILTIN_TYPE.semanticKey(), "type", "variable", "defaultLibrary"); + case SERVICE -> projection(SERVICE.semanticKey(), "class", "type", "defaultLibrary"); + case ERROR -> projection(ERROR.semanticKey(), "enum", "type"); + case ENUM -> projection(ENUM.semanticKey(), "enum", "type"); + case CALLBACK -> projection(CALLBACK.semanticKey(), "interface", "type"); + case GLOBAL -> projection(GLOBAL.semanticKey(), "variable", "variable", "readonly"); + case CONST -> projection(CONST.semanticKey(), "variable", "variable", "readonly"); + case IMPLEMENTS -> projection(IMPLEMENTS.semanticKey(), "keyword"); + case IDENTIFIER -> projection(IDENTIFIER.semanticKey(), "variable"); + }; + } + + private static FrontendHostProjectionEntrySpec projection( + final String semanticKey, + final String hostTokenType) { + return new FrontendHostProjectionEntrySpec(semanticKey, hostTokenType, java.util.List.of(), hostTokenType, java.util.List.of()); + } + + private static FrontendHostProjectionEntrySpec projection( + final String semanticKey, + final String hostTokenType, + final String fallbackTokenType) { + return new FrontendHostProjectionEntrySpec(semanticKey, hostTokenType, java.util.List.of(), fallbackTokenType, java.util.List.of()); + } + + private static FrontendHostProjectionEntrySpec projection( + final String semanticKey, + final String hostTokenType, + final String fallbackTokenType, + final String modifier) { + return new FrontendHostProjectionEntrySpec( + semanticKey, + hostTokenType, + java.util.List.of(modifier), + fallbackTokenType, + java.util.List.of(modifier)); + } +} diff --git a/prometeu-compiler/frontends/prometeu-frontend-pbs/src/test/java/p/studio/compiler/pbs/PbsSemanticPresentationContractTest.java b/prometeu-compiler/frontends/prometeu-frontend-pbs/src/test/java/p/studio/compiler/pbs/PbsSemanticPresentationContractTest.java index c78457c0..3e26eb5e 100644 --- a/prometeu-compiler/frontends/prometeu-frontend-pbs/src/test/java/p/studio/compiler/pbs/PbsSemanticPresentationContractTest.java +++ b/prometeu-compiler/frontends/prometeu-frontend-pbs/src/test/java/p/studio/compiler/pbs/PbsSemanticPresentationContractTest.java @@ -1,6 +1,7 @@ package p.studio.compiler.pbs; import org.junit.jupiter.api.Test; +import p.studio.compiler.PBSFrontendHostProjections; import p.studio.compiler.PBSDefinitions; import static org.junit.jupiter.api.Assertions.assertEquals; @@ -21,6 +22,7 @@ final class PbsSemanticPresentationContractTest { assertEquals("#d9e2ec", presentation.defaultTheme().editorPalette().baseForeground()); assertEquals("#569cd6", presentation.defaultTheme().requireTokenStyle("pbs-keyword").foreground()); assertTrue(presentation.defaultTheme().requireTokenStyle("pbs-comment").italic()); + assertEquals(PBSFrontendHostProjections.VSCODE_HOST_ID, presentation.requireHostProjection("vscode").hostId()); } @Test @@ -32,4 +34,19 @@ final class PbsSemanticPresentationContractTest { PbsSemanticKind.semanticKeys(), defaultTheme.tokenStyles().stream().map(tokenStyle -> tokenStyle.semanticKey()).toList()); } + + @Test + void shouldCoverTheWholePbsSemanticVocabularyInTheVscodeProjection() { + final var presentation = PBSDefinitions.PBS.getSemanticPresentation(); + final var vscodeProjection = presentation.requireHostProjection(PBSFrontendHostProjections.VSCODE_HOST_ID); + + assertEquals( + PbsSemanticKind.semanticKeys(), + vscodeProjection.tokenProjections().stream().map(tokenProjection -> tokenProjection.semanticKey()).toList()); + assertEquals("keyword", vscodeProjection.requireProjection(PbsSemanticKind.KEYWORD.semanticKey()).hostTokenType()); + assertEquals("type", vscodeProjection.requireProjection(PbsSemanticKind.STRUCT.semanticKey()).fallbackTokenType()); + assertEquals( + java.util.List.of("readonly"), + vscodeProjection.requireProjection(PbsSemanticKind.GLOBAL.semanticKey()).hostTokenModifiers()); + } } diff --git a/prometeu-compiler/prometeu-compiler-core/src/main/java/p/studio/compiler/models/FrontendHostProjectionEntrySpec.java b/prometeu-compiler/prometeu-compiler-core/src/main/java/p/studio/compiler/models/FrontendHostProjectionEntrySpec.java new file mode 100644 index 00000000..4d66ff4a --- /dev/null +++ b/prometeu-compiler/prometeu-compiler-core/src/main/java/p/studio/compiler/models/FrontendHostProjectionEntrySpec.java @@ -0,0 +1,38 @@ +package p.studio.compiler.models; + +import java.util.List; +import java.util.Objects; + +public record FrontendHostProjectionEntrySpec( + String semanticKey, + String hostTokenType, + List hostTokenModifiers, + String fallbackTokenType, + List fallbackTokenModifiers) { + + public FrontendHostProjectionEntrySpec { + semanticKey = requireText(semanticKey, "semanticKey"); + hostTokenType = requireText(hostTokenType, "hostTokenType"); + hostTokenModifiers = normalizeList(hostTokenModifiers, "hostTokenModifiers"); + fallbackTokenType = requireText(fallbackTokenType, "fallbackTokenType"); + fallbackTokenModifiers = normalizeList(fallbackTokenModifiers, "fallbackTokenModifiers"); + } + + private static List normalizeList( + final List values, + final String field) { + return List.copyOf(Objects.requireNonNull(values, field).stream() + .map(value -> requireText(value, field + " entry")) + .toList()); + } + + private static String requireText( + final String value, + final String field) { + final String candidate = Objects.requireNonNull(value, field).trim(); + if (candidate.isEmpty()) { + throw new IllegalArgumentException(field + " must not be blank"); + } + return candidate; + } +} diff --git a/prometeu-compiler/prometeu-compiler-core/src/main/java/p/studio/compiler/models/FrontendHostProjectionSpec.java b/prometeu-compiler/prometeu-compiler-core/src/main/java/p/studio/compiler/models/FrontendHostProjectionSpec.java new file mode 100644 index 00000000..826ab68f --- /dev/null +++ b/prometeu-compiler/prometeu-compiler-core/src/main/java/p/studio/compiler/models/FrontendHostProjectionSpec.java @@ -0,0 +1,48 @@ +package p.studio.compiler.models; + +import java.util.LinkedHashMap; +import java.util.List; +import java.util.Map; +import java.util.Objects; +import java.util.Optional; + +public record FrontendHostProjectionSpec( + String hostId, + List tokenProjections) { + + public FrontendHostProjectionSpec { + hostId = requireText(hostId, "hostId"); + tokenProjections = List.copyOf(Objects.requireNonNull(tokenProjections, "tokenProjections")); + if (tokenProjections.isEmpty()) { + throw new IllegalArgumentException("tokenProjections must not be empty"); + } + final Map bySemanticKey = new LinkedHashMap<>(); + for (final FrontendHostProjectionEntrySpec tokenProjection : tokenProjections) { + final FrontendHostProjectionEntrySpec previous = bySemanticKey.put(tokenProjection.semanticKey(), tokenProjection); + if (previous != null) { + throw new IllegalArgumentException("duplicate host projection for semantic key: " + tokenProjection.semanticKey()); + } + } + } + + public Optional projectionFor(final String semanticKey) { + return tokenProjections.stream() + .filter(tokenProjection -> tokenProjection.semanticKey().equals(semanticKey)) + .findFirst(); + } + + public FrontendHostProjectionEntrySpec requireProjection(final String semanticKey) { + return projectionFor(semanticKey) + .orElseThrow(() -> new IllegalArgumentException("missing host projection for semantic key: " + semanticKey)); + } + + private static String requireText( + final String value, + final String field) { + final String candidate = Objects.requireNonNull(value, field).trim(); + if (candidate.isEmpty()) { + throw new IllegalArgumentException(field + " must not be blank"); + } + return candidate; + } +} diff --git a/prometeu-compiler/prometeu-compiler-core/src/main/java/p/studio/compiler/models/FrontendSemanticPresentationSpec.java b/prometeu-compiler/prometeu-compiler-core/src/main/java/p/studio/compiler/models/FrontendSemanticPresentationSpec.java index 989f5959..5de32aa9 100644 --- a/prometeu-compiler/prometeu-compiler-core/src/main/java/p/studio/compiler/models/FrontendSemanticPresentationSpec.java +++ b/prometeu-compiler/prometeu-compiler-core/src/main/java/p/studio/compiler/models/FrontendSemanticPresentationSpec.java @@ -6,12 +6,21 @@ import java.util.Objects; public record FrontendSemanticPresentationSpec( List semanticKeys, List themes, - String defaultThemeId) { + String defaultThemeId, + List hostProjections) { + + public FrontendSemanticPresentationSpec( + final List semanticKeys, + final List themes, + final String defaultThemeId) { + this(semanticKeys, themes, defaultThemeId, List.of()); + } public FrontendSemanticPresentationSpec { semanticKeys = List.copyOf(Objects.requireNonNull(semanticKeys, "semanticKeys")); themes = List.copyOf(Objects.requireNonNull(themes, "themes")); defaultThemeId = Objects.requireNonNull(defaultThemeId, "defaultThemeId").trim(); + hostProjections = List.copyOf(Objects.requireNonNull(hostProjections, "hostProjections")); if (semanticKeys.isEmpty() && themes.isEmpty()) { if (!defaultThemeId.isEmpty()) { throw new IllegalArgumentException("defaultThemeId must be blank when no themes are declared"); @@ -25,10 +34,27 @@ public record FrontendSemanticPresentationSpec( throw new IllegalArgumentException("defaultThemeId must reference one of the declared themes"); } } + final List normalizedSemanticKeys = semanticKeys.stream() + .map(key -> requireText(key, "semanticKeys entry")) + .toList(); + final var hostIds = new java.util.LinkedHashSet(); + for (final FrontendHostProjectionSpec hostProjection : hostProjections) { + if (!hostIds.add(hostProjection.hostId())) { + throw new IllegalArgumentException("duplicate host projection for hostId: " + hostProjection.hostId()); + } + for (final FrontendHostProjectionEntrySpec tokenProjection : hostProjection.tokenProjections()) { + if (!normalizedSemanticKeys.contains(tokenProjection.semanticKey())) { + throw new IllegalArgumentException( + "host projection for hostId '" + hostProjection.hostId() + "' references unknown semantic key: " + + tokenProjection.semanticKey()); + } + } + } + semanticKeys = normalizedSemanticKeys; } public static FrontendSemanticPresentationSpec empty() { - return new FrontendSemanticPresentationSpec(List.of(), List.of(), ""); + return new FrontendSemanticPresentationSpec(List.of(), List.of(), "", List.of()); } public FrontendVisualThemeSpec defaultTheme() { @@ -42,7 +68,18 @@ public record FrontendSemanticPresentationSpec( } public boolean isEmpty() { - return semanticKeys.isEmpty() && themes.isEmpty() && defaultThemeId.isEmpty(); + return semanticKeys.isEmpty() && themes.isEmpty() && defaultThemeId.isEmpty() && hostProjections.isEmpty(); + } + + public java.util.Optional hostProjection(final String hostId) { + return hostProjections.stream() + .filter(hostProjection -> hostProjection.hostId().equals(requireText(hostId, "hostId"))) + .findFirst(); + } + + public FrontendHostProjectionSpec requireHostProjection(final String hostId) { + return hostProjection(hostId) + .orElseThrow(() -> new IllegalArgumentException("missing host projection for hostId: " + hostId)); } private static String requireText( diff --git a/prometeu-compiler/prometeu-compiler-core/src/test/java/p/studio/compiler/models/FrontendSemanticPresentationSpecTest.java b/prometeu-compiler/prometeu-compiler-core/src/test/java/p/studio/compiler/models/FrontendSemanticPresentationSpecTest.java new file mode 100644 index 00000000..ded116dd --- /dev/null +++ b/prometeu-compiler/prometeu-compiler-core/src/test/java/p/studio/compiler/models/FrontendSemanticPresentationSpecTest.java @@ -0,0 +1,85 @@ +package p.studio.compiler.models; + +import org.junit.jupiter.api.Test; + +import java.util.List; + +import static org.junit.jupiter.api.Assertions.assertEquals; +import static org.junit.jupiter.api.Assertions.assertThrows; + +final class FrontendSemanticPresentationSpecTest { + + @Test + void shouldExposeHostProjectionByHostId() { + final var presentation = new FrontendSemanticPresentationSpec( + List.of("demo-key"), + List.of(new FrontendVisualThemeSpec( + "demo-theme", + "Demo Theme", + new FrontendEditorPaletteSpec("#111111", "#eeeeee", "#333333", "#777777", "#111111", "#222222", "#eeeeee"), + List.of(new FrontendTokenStyleSpec("demo-key", "#eeeeee", false, false, false)))), + "demo-theme", + List.of(new FrontendHostProjectionSpec( + "vscode", + List.of(new FrontendHostProjectionEntrySpec( + "demo-key", + "keyword", + List.of("declaration"), + "variable", + List.of()))))); + + final var vscodeProjection = presentation.requireHostProjection("vscode").requireProjection("demo-key"); + assertEquals("keyword", vscodeProjection.hostTokenType()); + assertEquals(List.of("declaration"), vscodeProjection.hostTokenModifiers()); + assertEquals("variable", vscodeProjection.fallbackTokenType()); + } + + @Test + void shouldRejectDuplicateHostIds() { + assertThrows(IllegalArgumentException.class, () -> new FrontendSemanticPresentationSpec( + List.of("demo-key"), + List.of(new FrontendVisualThemeSpec( + "demo-theme", + "Demo Theme", + new FrontendEditorPaletteSpec("#111111", "#eeeeee", "#333333", "#777777", "#111111", "#222222", "#eeeeee"), + List.of(new FrontendTokenStyleSpec("demo-key", "#eeeeee", false, false, false)))), + "demo-theme", + List.of( + new FrontendHostProjectionSpec( + "vscode", + List.of(new FrontendHostProjectionEntrySpec( + "demo-key", + "keyword", + List.of(), + "variable", + List.of()))), + new FrontendHostProjectionSpec( + "vscode", + List.of(new FrontendHostProjectionEntrySpec( + "demo-key", + "type", + List.of(), + "variable", + List.of())))))); + } + + @Test + void shouldRejectProjectionForUnknownSemanticKey() { + assertThrows(IllegalArgumentException.class, () -> new FrontendSemanticPresentationSpec( + List.of("demo-key"), + List.of(new FrontendVisualThemeSpec( + "demo-theme", + "Demo Theme", + new FrontendEditorPaletteSpec("#111111", "#eeeeee", "#333333", "#777777", "#111111", "#222222", "#eeeeee"), + List.of(new FrontendTokenStyleSpec("demo-key", "#eeeeee", false, false, false)))), + "demo-theme", + List.of(new FrontendHostProjectionSpec( + "vscode", + List.of(new FrontendHostProjectionEntrySpec( + "unknown-key", + "keyword", + List.of(), + "variable", + List.of())))))); + } +} -- 2.47.2 From e5ab4cd021a25339f9d7670c473bbe6e0004417f Mon Sep 17 00:00:00 2001 From: bQUARKz Date: Wed, 6 May 2026 15:26:24 +0100 Subject: [PATCH 24/37] implements PLN-0073 --- discussion/index.ndjson | 2 +- ...-lsp-semantic-host-projection-transport.md | 4 +- .../BaselineSemanticHostProjection.java | 27 ++++++++ .../BaselineSemanticHostProjectionEntry.java | 38 ++++++++++++ .../messages/BaselineServerDescription.java | 8 +++ .../CompilerLanguageServiceBridge.java | 25 +++++++- .../mapping/Lsp4jProtocolMessageMapper.java | 19 +++++- .../CompilerLanguageServiceBridgeTest.java | 5 ++ .../protocol/PrometeuLanguageServerTest.java | 10 +++ .../Lsp4jProtocolMessageMapperTest.java | 62 +++++++++++++++++++ 10 files changed, 193 insertions(+), 7 deletions(-) create mode 100644 prometeu-lsp/prometeu-lsp-v1/src/main/java/p/studio/lsp/messages/BaselineSemanticHostProjection.java create mode 100644 prometeu-lsp/prometeu-lsp-v1/src/main/java/p/studio/lsp/messages/BaselineSemanticHostProjectionEntry.java create mode 100644 prometeu-lsp/prometeu-lsp-v1/src/test/java/p/studio/lsp/services/protocol/mapping/Lsp4jProtocolMessageMapperTest.java diff --git a/discussion/index.ndjson b/discussion/index.ndjson index 17cc4fc5..3052a833 100644 --- a/discussion/index.ndjson +++ b/discussion/index.ndjson @@ -1,5 +1,5 @@ {"type":"meta","next_id":{"DSC":35,"AGD":38,"DEC":35,"PLN":75,"LSN":47,"CLSN":1}} -{"type":"discussion","id":"DSC-0034","status":"in_progress","ticket":"frontend-semantic-host-projection-flexibility","title":"Frontend semantic vocabulary flexibility and declarative host projection","created_at":"2026-05-06","updated_at":"2026-05-06","tags":["compiler","compiler-general","frontend","semantics","vscode","host-projection","lsp"],"agendas":[{"id":"AGD-0037","file":"AGD-0037-frontend-semantic-host-projection-flexibility.md","status":"accepted","created_at":"2026-05-06","updated_at":"2026-05-06"}],"decisions":[{"id":"DEC-0034","file":"DEC-0034-frontend-semantic-host-projection-flexibility.md","status":"accepted","created_at":"2026-05-06","updated_at":"2026-05-06","ref_agenda":"AGD-0037"}],"plans":[{"id":"PLN-0072","file":"PLN-0072-frontend-semantic-host-projection-contract.md","status":"done","created_at":"2026-05-06","updated_at":"2026-05-06","ref_decisions":["DEC-0034"]},{"id":"PLN-0073","file":"PLN-0073-lsp-semantic-host-projection-transport.md","status":"open","created_at":"2026-05-06","updated_at":"2026-05-06","ref_decisions":["DEC-0034"]},{"id":"PLN-0074","file":"PLN-0074-vscode-semantic-host-projection-adapter.md","status":"open","created_at":"2026-05-06","updated_at":"2026-05-06","ref_decisions":["DEC-0034"]}],"lessons":[]} +{"type":"discussion","id":"DSC-0034","status":"in_progress","ticket":"frontend-semantic-host-projection-flexibility","title":"Frontend semantic vocabulary flexibility and declarative host projection","created_at":"2026-05-06","updated_at":"2026-05-06","tags":["compiler","compiler-general","frontend","semantics","vscode","host-projection","lsp"],"agendas":[{"id":"AGD-0037","file":"AGD-0037-frontend-semantic-host-projection-flexibility.md","status":"accepted","created_at":"2026-05-06","updated_at":"2026-05-06"}],"decisions":[{"id":"DEC-0034","file":"DEC-0034-frontend-semantic-host-projection-flexibility.md","status":"accepted","created_at":"2026-05-06","updated_at":"2026-05-06","ref_agenda":"AGD-0037"}],"plans":[{"id":"PLN-0072","file":"PLN-0072-frontend-semantic-host-projection-contract.md","status":"done","created_at":"2026-05-06","updated_at":"2026-05-06","ref_decisions":["DEC-0034"]},{"id":"PLN-0073","file":"PLN-0073-lsp-semantic-host-projection-transport.md","status":"done","created_at":"2026-05-06","updated_at":"2026-05-06","ref_decisions":["DEC-0034"]},{"id":"PLN-0074","file":"PLN-0074-vscode-semantic-host-projection-adapter.md","status":"open","created_at":"2026-05-06","updated_at":"2026-05-06","ref_decisions":["DEC-0034"]}],"lessons":[]} {"type":"discussion","id":"DSC-0033","status":"in_progress","ticket":"frontend-visual-theme-spec-and-css-retirement","title":"Frontend visual theme spec and retirement of host-consumed semantic CSS","created_at":"2026-05-06","updated_at":"2026-05-06","tags":["compiler","compiler-general","frontend","presentation","theming","studio","vscode","lsp","pbs"],"agendas":[{"id":"AGD-0036","file":"AGD-0036-frontend-visual-theme-spec-and-css-retirement.md","status":"accepted","created_at":"2026-05-06","updated_at":"2026-05-06"}],"decisions":[{"id":"DEC-0033","file":"DEC-0033-frontend-visual-theme-spec-and-css-retirement.md","status":"accepted","created_at":"2026-05-06","updated_at":"2026-05-06","ref_agenda":"AGD-0036"}],"plans":[{"id":"PLN-0068","file":"PLN-0068-frontend-visual-contract-and-pbs-migration.md","status":"open","created_at":"2026-05-06","updated_at":"2026-05-06","ref_decisions":["DEC-0033"]},{"id":"PLN-0069","file":"PLN-0069-lsp-visual-theme-transport-and-selection.md","status":"open","created_at":"2026-05-06","updated_at":"2026-05-06","ref_decisions":["DEC-0033"]},{"id":"PLN-0070","file":"PLN-0070-studio-visual-theme-adapter-and-css-retirement.md","status":"open","created_at":"2026-05-06","updated_at":"2026-05-06","ref_decisions":["DEC-0033"]},{"id":"PLN-0071","file":"PLN-0071-vscode-dynamic-theme-translation-adapter.md","status":"open","created_at":"2026-05-06","updated_at":"2026-05-06","ref_decisions":["DEC-0033"]}],"lessons":[]} {"type":"discussion","id":"DSC-0032","status":"in_progress","ticket":"studio-new-lsp-api-and-v1-boundary","title":"Novo boundary entre lsp-api, lsp-v1 e a extensao VS Code","created_at":"2026-05-05","updated_at":"2026-05-05","tags":["studio","lsp","vscode","protocol","api","boundary"],"agendas":[{"id":"AGD-0035","file":"AGD-0035-studio-new-lsp-api-and-v1-boundary.md","status":"accepted","created_at":"2026-05-05","updated_at":"2026-05-05"}],"decisions":[{"id":"DEC-0032","file":"DEC-0032-studio-new-lsp-api-and-v1-boundary.md","status":"accepted","created_at":"2026-05-05","updated_at":"2026-05-05","ref_agenda":"AGD-0035"}],"plans":[{"id":"PLN-0065","file":"PLN-0065-lsp-boundary-and-module-scaffolding.md","status":"done","created_at":"2026-05-05","updated_at":"2026-05-05","ref_decisions":["DEC-0032"]},{"id":"PLN-0066","file":"PLN-0066-project-scoped-lsp-server-lifecycle-in-studio.md","status":"done","created_at":"2026-05-05","updated_at":"2026-05-05","ref_decisions":["DEC-0032"]},{"id":"PLN-0067","file":"PLN-0067-compiler-backed-dumb-lsp-server-baseline.md","status":"done","created_at":"2026-05-05","updated_at":"2026-05-05","ref_decisions":["DEC-0032"]}],"lessons":[]} {"type":"discussion","id":"DSC-0031","status":"in_progress","ticket":"studio-editor-workspace-cleanup","title":"Limpeza completa do Workspace Editor do Studio e remoção dos acoplamentos legados","created_at":"2026-05-05","updated_at":"2026-05-05","tags":["studio","editor","cleanup","vfs","lsp","migration"],"agendas":[{"id":"AGD-0034","file":"AGD-0034-vscode-editor-migration-feasibility.md","status":"accepted","created_at":"2026-05-05","updated_at":"2026-05-05"}],"decisions":[{"id":"DEC-0031","file":"DEC-0031-studio-editor-workspace-cleanup.md","status":"in_progress","created_at":"2026-05-05","updated_at":"2026-05-05","ref_agenda":"AGD-0034"}],"plans":[{"id":"PLN-0062","file":"PLN-0062-shell-session-and-state-cleanup-after-editor-removal.md","status":"done","created_at":"2026-05-05","updated_at":"2026-05-05","ref_decisions":["DEC-0031"]},{"id":"PLN-0063","file":"PLN-0063-legacy-lsp-and-vfs-module-removal-with-runtime-preservation.md","status":"done","created_at":"2026-05-05","updated_at":"2026-05-05","ref_decisions":["DEC-0031"]},{"id":"PLN-0064","file":"PLN-0064-normative-test-and-lesson-cleanup-for-editor-stack-removal.md","status":"done","created_at":"2026-05-05","updated_at":"2026-05-05","ref_decisions":["DEC-0031"]}],"lessons":[]} diff --git a/discussion/workflow/plans/PLN-0073-lsp-semantic-host-projection-transport.md b/discussion/workflow/plans/PLN-0073-lsp-semantic-host-projection-transport.md index 3c7ea505..038e6bad 100644 --- a/discussion/workflow/plans/PLN-0073-lsp-semantic-host-projection-transport.md +++ b/discussion/workflow/plans/PLN-0073-lsp-semantic-host-projection-transport.md @@ -2,9 +2,9 @@ id: PLN-0073 ticket: frontend-semantic-host-projection-flexibility title: LSP Semantic Host Projection Transport -status: open +status: done created: 2026-05-06 -completed: +completed: 2026-05-06 tags: [lsp, compiler, frontend, semantics, host-projection, vscode, protocol] --- diff --git a/prometeu-lsp/prometeu-lsp-v1/src/main/java/p/studio/lsp/messages/BaselineSemanticHostProjection.java b/prometeu-lsp/prometeu-lsp-v1/src/main/java/p/studio/lsp/messages/BaselineSemanticHostProjection.java new file mode 100644 index 00000000..ed617665 --- /dev/null +++ b/prometeu-lsp/prometeu-lsp-v1/src/main/java/p/studio/lsp/messages/BaselineSemanticHostProjection.java @@ -0,0 +1,27 @@ +package p.studio.lsp.messages; + +import java.util.List; +import java.util.Objects; + +public record BaselineSemanticHostProjection( + String hostId, + List tokenProjections) { + + public BaselineSemanticHostProjection { + hostId = requireText(hostId, "hostId"); + tokenProjections = List.copyOf(Objects.requireNonNull(tokenProjections, "tokenProjections")); + if (tokenProjections.isEmpty()) { + throw new IllegalArgumentException("tokenProjections must not be empty"); + } + } + + private static String requireText( + final String value, + final String field) { + final String candidate = Objects.requireNonNull(value, field).trim(); + if (candidate.isEmpty()) { + throw new IllegalArgumentException(field + " must not be blank"); + } + return candidate; + } +} diff --git a/prometeu-lsp/prometeu-lsp-v1/src/main/java/p/studio/lsp/messages/BaselineSemanticHostProjectionEntry.java b/prometeu-lsp/prometeu-lsp-v1/src/main/java/p/studio/lsp/messages/BaselineSemanticHostProjectionEntry.java new file mode 100644 index 00000000..406332e8 --- /dev/null +++ b/prometeu-lsp/prometeu-lsp-v1/src/main/java/p/studio/lsp/messages/BaselineSemanticHostProjectionEntry.java @@ -0,0 +1,38 @@ +package p.studio.lsp.messages; + +import java.util.List; +import java.util.Objects; + +public record BaselineSemanticHostProjectionEntry( + String semanticKey, + String hostTokenType, + List hostTokenModifiers, + String fallbackTokenType, + List fallbackTokenModifiers) { + + public BaselineSemanticHostProjectionEntry { + semanticKey = requireText(semanticKey, "semanticKey"); + hostTokenType = requireText(hostTokenType, "hostTokenType"); + hostTokenModifiers = normalizeList(hostTokenModifiers, "hostTokenModifiers"); + fallbackTokenType = requireText(fallbackTokenType, "fallbackTokenType"); + fallbackTokenModifiers = normalizeList(fallbackTokenModifiers, "fallbackTokenModifiers"); + } + + private static List normalizeList( + final List values, + final String field) { + return List.copyOf(Objects.requireNonNull(values, field).stream() + .map(value -> requireText(value, field + " entry")) + .toList()); + } + + private static String requireText( + final String value, + final String field) { + final String candidate = Objects.requireNonNull(value, field).trim(); + if (candidate.isEmpty()) { + throw new IllegalArgumentException(field + " must not be blank"); + } + return candidate; + } +} diff --git a/prometeu-lsp/prometeu-lsp-v1/src/main/java/p/studio/lsp/messages/BaselineServerDescription.java b/prometeu-lsp/prometeu-lsp-v1/src/main/java/p/studio/lsp/messages/BaselineServerDescription.java index 9734f319..6af55458 100644 --- a/prometeu-lsp/prometeu-lsp-v1/src/main/java/p/studio/lsp/messages/BaselineServerDescription.java +++ b/prometeu-lsp/prometeu-lsp-v1/src/main/java/p/studio/lsp/messages/BaselineServerDescription.java @@ -9,6 +9,7 @@ public record BaselineServerDescription( String frontendLanguageId, boolean hoverSupported, List semanticTokenTypes, + List semanticHostProjections, List visualThemes, String activeVisualThemeId) { @@ -17,8 +18,15 @@ public record BaselineServerDescription( version = requireText(version, "version"); frontendLanguageId = requireText(frontendLanguageId, "frontendLanguageId"); semanticTokenTypes = List.copyOf(Objects.requireNonNull(semanticTokenTypes, "semanticTokenTypes")); + semanticHostProjections = List.copyOf(Objects.requireNonNull(semanticHostProjections, "semanticHostProjections")); visualThemes = List.copyOf(Objects.requireNonNull(visualThemes, "visualThemes")); activeVisualThemeId = requireText(activeVisualThemeId, "activeVisualThemeId"); + final var hostIds = new java.util.LinkedHashSet(); + for (final BaselineSemanticHostProjection hostProjection : semanticHostProjections) { + if (!hostIds.add(hostProjection.hostId())) { + throw new IllegalArgumentException("duplicate semantic host projection for hostId: " + hostProjection.hostId()); + } + } if (visualThemes.stream().map(BaselineVisualTheme::themeId).noneMatch(activeVisualThemeId::equals)) { throw new IllegalArgumentException("activeVisualThemeId must reference one of the declared visual themes"); } diff --git a/prometeu-lsp/prometeu-lsp-v1/src/main/java/p/studio/lsp/services/compiler/CompilerLanguageServiceBridge.java b/prometeu-lsp/prometeu-lsp-v1/src/main/java/p/studio/lsp/services/compiler/CompilerLanguageServiceBridge.java index 534c3ffa..c85617d8 100644 --- a/prometeu-lsp/prometeu-lsp-v1/src/main/java/p/studio/lsp/services/compiler/CompilerLanguageServiceBridge.java +++ b/prometeu-lsp/prometeu-lsp-v1/src/main/java/p/studio/lsp/services/compiler/CompilerLanguageServiceBridge.java @@ -6,6 +6,8 @@ import p.studio.compiler.messages.BuildingIssue; import p.studio.compiler.models.AnalysisSnapshot; import p.studio.compiler.models.BuilderPipelineContext; import p.studio.compiler.models.FrontendEditorPaletteSpec; +import p.studio.compiler.models.FrontendHostProjectionEntrySpec; +import p.studio.compiler.models.FrontendHostProjectionSpec; import p.studio.compiler.PBSDefinitions; import p.studio.compiler.models.FrontendTokenStyleSpec; import p.studio.compiler.models.FrontendVisualThemeSpec; @@ -33,14 +35,16 @@ public record CompilerLanguageServiceBridge() implements LanguageServiceBridge { @Override public BaselineServerDescription describeServer(final LspProjectContext context) { Objects.requireNonNull(context, "context"); + final var presentation = PBSDefinitions.PBS.getSemanticPresentation(); return new BaselineServerDescription( "Prometeu Studio LSP", "0.1.0", context.languageId(), true, - PBSDefinitions.PBS.getSemanticPresentation().semanticKeys(), - PBSDefinitions.PBS.getSemanticPresentation().themes().stream().map(this::mapVisualTheme).toList(), - PBSDefinitions.PBS.getSemanticPresentation().defaultThemeId()); + presentation.semanticKeys(), + presentation.hostProjections().stream().map(this::mapSemanticHostProjection).toList(), + presentation.themes().stream().map(this::mapVisualTheme).toList(), + presentation.defaultThemeId()); } @Override @@ -205,6 +209,21 @@ public record CompilerLanguageServiceBridge() implements LanguageServiceBridge { theme.tokenStyles().stream().map(this::mapTokenStyle).toList()); } + private BaselineSemanticHostProjection mapSemanticHostProjection(final FrontendHostProjectionSpec hostProjection) { + return new BaselineSemanticHostProjection( + hostProjection.hostId(), + hostProjection.tokenProjections().stream().map(this::mapSemanticHostProjectionEntry).toList()); + } + + private BaselineSemanticHostProjectionEntry mapSemanticHostProjectionEntry(final FrontendHostProjectionEntrySpec tokenProjection) { + return new BaselineSemanticHostProjectionEntry( + tokenProjection.semanticKey(), + tokenProjection.hostTokenType(), + tokenProjection.hostTokenModifiers(), + tokenProjection.fallbackTokenType(), + tokenProjection.fallbackTokenModifiers()); + } + private BaselineEditorPalette mapEditorPalette(final FrontendEditorPaletteSpec palette) { return new BaselineEditorPalette( palette.baseForeground(), diff --git a/prometeu-lsp/prometeu-lsp-v1/src/main/java/p/studio/lsp/services/protocol/mapping/Lsp4jProtocolMessageMapper.java b/prometeu-lsp/prometeu-lsp-v1/src/main/java/p/studio/lsp/services/protocol/mapping/Lsp4jProtocolMessageMapper.java index aba2dd5f..48caa92a 100644 --- a/prometeu-lsp/prometeu-lsp-v1/src/main/java/p/studio/lsp/services/protocol/mapping/Lsp4jProtocolMessageMapper.java +++ b/prometeu-lsp/prometeu-lsp-v1/src/main/java/p/studio/lsp/services/protocol/mapping/Lsp4jProtocolMessageMapper.java @@ -33,7 +33,12 @@ public final class Lsp4jProtocolMessageMapper implements ProtocolMessageMapper { Map.of( "frontendLanguageId", description.frontendLanguageId(), "activeVisualThemeId", description.activeVisualThemeId(), - "visualThemes", description.visualThemes().stream().map(this::mapVisualThemePayload).toList()))); + "visualThemes", description.visualThemes().stream().map(this::mapVisualThemePayload).toList()), + "prometeuSemanticHostProjections", + Map.of( + "frontendLanguageId", description.frontendLanguageId(), + "semanticKeys", description.semanticTokenTypes(), + "hostProjections", description.semanticHostProjections().stream().map(this::mapSemanticHostProjectionPayload).toList()))); final InitializeResult result = new InitializeResult(capabilities); final ServerInfo serverInfo = new ServerInfo(); @@ -151,4 +156,16 @@ public final class Lsp4jProtocolMessageMapper implements ProtocolMessageMapper { "underline", tokenStyle.underline())).toList()); return payload; } + + private Map mapSemanticHostProjectionPayload(final BaselineSemanticHostProjection hostProjection) { + final Map payload = new LinkedHashMap<>(); + payload.put("hostId", hostProjection.hostId()); + payload.put("tokenProjections", hostProjection.tokenProjections().stream().map(tokenProjection -> Map.of( + "semanticKey", tokenProjection.semanticKey(), + "hostTokenType", tokenProjection.hostTokenType(), + "hostTokenModifiers", tokenProjection.hostTokenModifiers(), + "fallbackTokenType", tokenProjection.fallbackTokenType(), + "fallbackTokenModifiers", tokenProjection.fallbackTokenModifiers())).toList()); + return payload; + } } diff --git a/prometeu-lsp/prometeu-lsp-v1/src/test/java/p/studio/lsp/services/compiler/CompilerLanguageServiceBridgeTest.java b/prometeu-lsp/prometeu-lsp-v1/src/test/java/p/studio/lsp/services/compiler/CompilerLanguageServiceBridgeTest.java index e613bb54..1c3c0a61 100644 --- a/prometeu-lsp/prometeu-lsp-v1/src/test/java/p/studio/lsp/services/compiler/CompilerLanguageServiceBridgeTest.java +++ b/prometeu-lsp/prometeu-lsp-v1/src/test/java/p/studio/lsp/services/compiler/CompilerLanguageServiceBridgeTest.java @@ -64,6 +64,11 @@ class CompilerLanguageServiceBridgeTest { assertEquals("pbs", description.frontendLanguageId()); assertEquals("pbs-default", description.activeVisualThemeId()); + assertEquals(1, description.semanticHostProjections().size()); + assertEquals("vscode", description.semanticHostProjections().getFirst().hostId()); + assertTrue(description.semanticHostProjections().getFirst().tokenProjections().stream() + .anyMatch(tokenProjection -> tokenProjection.semanticKey().equals("pbs-keyword") + && tokenProjection.hostTokenType().equals("keyword"))); assertEquals(1, description.visualThemes().size()); assertEquals("PBS Default", description.visualThemes().getFirst().displayName()); assertEquals("#d9e2ec", description.visualThemes().getFirst().editorPalette().baseForeground()); diff --git a/prometeu-lsp/prometeu-lsp-v1/src/test/java/p/studio/lsp/services/protocol/PrometeuLanguageServerTest.java b/prometeu-lsp/prometeu-lsp-v1/src/test/java/p/studio/lsp/services/protocol/PrometeuLanguageServerTest.java index f59b745c..5b4fc14d 100644 --- a/prometeu-lsp/prometeu-lsp-v1/src/test/java/p/studio/lsp/services/protocol/PrometeuLanguageServerTest.java +++ b/prometeu-lsp/prometeu-lsp-v1/src/test/java/p/studio/lsp/services/protocol/PrometeuLanguageServerTest.java @@ -14,6 +14,8 @@ import org.junit.jupiter.api.Test; import p.studio.lsp.messages.BaselineDocumentAnalysis; import p.studio.lsp.messages.BaselineEditorPalette; import p.studio.lsp.messages.BaselineHover; +import p.studio.lsp.messages.BaselineSemanticHostProjection; +import p.studio.lsp.messages.BaselineSemanticHostProjectionEntry; import p.studio.lsp.messages.BaselineSemanticTokens; import p.studio.lsp.messages.BaselineServerDescription; import p.studio.lsp.messages.BaselineTokenStyle; @@ -89,6 +91,14 @@ class PrometeuLanguageServerTest { "pbs", true, List.of(), + List.of(new BaselineSemanticHostProjection( + "vscode", + List.of(new BaselineSemanticHostProjectionEntry( + "demo-keyword", + "keyword", + List.of(), + "variable", + List.of())))), List.of(new BaselineVisualTheme( "demo-default", "Demo Default", diff --git a/prometeu-lsp/prometeu-lsp-v1/src/test/java/p/studio/lsp/services/protocol/mapping/Lsp4jProtocolMessageMapperTest.java b/prometeu-lsp/prometeu-lsp-v1/src/test/java/p/studio/lsp/services/protocol/mapping/Lsp4jProtocolMessageMapperTest.java new file mode 100644 index 00000000..bf6a9b24 --- /dev/null +++ b/prometeu-lsp/prometeu-lsp-v1/src/test/java/p/studio/lsp/services/protocol/mapping/Lsp4jProtocolMessageMapperTest.java @@ -0,0 +1,62 @@ +package p.studio.lsp.services.protocol.mapping; + +import org.eclipse.lsp4j.InitializeResult; +import org.junit.jupiter.api.Test; +import p.studio.lsp.messages.BaselineEditorPalette; +import p.studio.lsp.messages.BaselineSemanticHostProjection; +import p.studio.lsp.messages.BaselineSemanticHostProjectionEntry; +import p.studio.lsp.messages.BaselineServerDescription; +import p.studio.lsp.messages.BaselineTokenStyle; +import p.studio.lsp.messages.BaselineVisualTheme; + +import java.util.List; +import java.util.Map; + +import static org.junit.jupiter.api.Assertions.assertEquals; +import static org.junit.jupiter.api.Assertions.assertInstanceOf; + +final class Lsp4jProtocolMessageMapperTest { + + @Test + void initializeResultPublishesCanonicalKeysAndHostProjectionPayload() { + final var mapper = new Lsp4jProtocolMessageMapper(); + final var description = new BaselineServerDescription( + "demo", + "1", + "pbs", + true, + List.of("demo-keyword"), + List.of(new BaselineSemanticHostProjection( + "vscode", + List.of(new BaselineSemanticHostProjectionEntry( + "demo-keyword", + "keyword", + List.of("declaration"), + "variable", + List.of())))), + List.of(new BaselineVisualTheme( + "demo-default", + "Demo Default", + new BaselineEditorPalette("#111111", "#222222", "#333333", "#444444", "#555555", "#666666", "#777777"), + List.of(new BaselineTokenStyle("demo-keyword", "#888888", false, false, false)))), + "demo-default"); + + final InitializeResult result = mapper.mapInitializeResult(description); + + final var experimental = assertInstanceOf(Map.class, result.getCapabilities().getExperimental()); + final var semanticPayload = assertInstanceOf(Map.class, experimental.get("prometeuSemanticHostProjections")); + assertEquals("pbs", semanticPayload.get("frontendLanguageId")); + assertEquals(List.of("demo-keyword"), semanticPayload.get("semanticKeys")); + + final var hostProjectionPayloads = assertInstanceOf(List.class, semanticPayload.get("hostProjections")); + final var firstHostProjection = assertInstanceOf(Map.class, hostProjectionPayloads.getFirst()); + assertEquals("vscode", firstHostProjection.get("hostId")); + + final var tokenProjectionPayloads = assertInstanceOf(List.class, firstHostProjection.get("tokenProjections")); + final var firstTokenProjection = assertInstanceOf(Map.class, tokenProjectionPayloads.getFirst()); + assertEquals("demo-keyword", firstTokenProjection.get("semanticKey")); + assertEquals("keyword", firstTokenProjection.get("hostTokenType")); + assertEquals(List.of("declaration"), firstTokenProjection.get("hostTokenModifiers")); + assertEquals("variable", firstTokenProjection.get("fallbackTokenType")); + } +} -- 2.47.2 From 7ae2e94d63fa2ceedb7dc7df10b2c5f7933e1ac9 Mon Sep 17 00:00:00 2001 From: bQUARKz Date: Wed, 6 May 2026 15:28:37 +0100 Subject: [PATCH 25/37] implements PLN-0074 --- discussion/index.ndjson | 2 +- ...vscode-semantic-host-projection-adapter.md | 4 +- tools/vscode-extension/out/extension.js | 84 +++++++++--- tools/vscode-extension/package.json | 94 -------------- tools/vscode-extension/src/extension.ts | 120 +++++++++++++++--- 5 files changed, 170 insertions(+), 134 deletions(-) diff --git a/discussion/index.ndjson b/discussion/index.ndjson index 3052a833..f17e173d 100644 --- a/discussion/index.ndjson +++ b/discussion/index.ndjson @@ -1,5 +1,5 @@ {"type":"meta","next_id":{"DSC":35,"AGD":38,"DEC":35,"PLN":75,"LSN":47,"CLSN":1}} -{"type":"discussion","id":"DSC-0034","status":"in_progress","ticket":"frontend-semantic-host-projection-flexibility","title":"Frontend semantic vocabulary flexibility and declarative host projection","created_at":"2026-05-06","updated_at":"2026-05-06","tags":["compiler","compiler-general","frontend","semantics","vscode","host-projection","lsp"],"agendas":[{"id":"AGD-0037","file":"AGD-0037-frontend-semantic-host-projection-flexibility.md","status":"accepted","created_at":"2026-05-06","updated_at":"2026-05-06"}],"decisions":[{"id":"DEC-0034","file":"DEC-0034-frontend-semantic-host-projection-flexibility.md","status":"accepted","created_at":"2026-05-06","updated_at":"2026-05-06","ref_agenda":"AGD-0037"}],"plans":[{"id":"PLN-0072","file":"PLN-0072-frontend-semantic-host-projection-contract.md","status":"done","created_at":"2026-05-06","updated_at":"2026-05-06","ref_decisions":["DEC-0034"]},{"id":"PLN-0073","file":"PLN-0073-lsp-semantic-host-projection-transport.md","status":"done","created_at":"2026-05-06","updated_at":"2026-05-06","ref_decisions":["DEC-0034"]},{"id":"PLN-0074","file":"PLN-0074-vscode-semantic-host-projection-adapter.md","status":"open","created_at":"2026-05-06","updated_at":"2026-05-06","ref_decisions":["DEC-0034"]}],"lessons":[]} +{"type":"discussion","id":"DSC-0034","status":"in_progress","ticket":"frontend-semantic-host-projection-flexibility","title":"Frontend semantic vocabulary flexibility and declarative host projection","created_at":"2026-05-06","updated_at":"2026-05-06","tags":["compiler","compiler-general","frontend","semantics","vscode","host-projection","lsp"],"agendas":[{"id":"AGD-0037","file":"AGD-0037-frontend-semantic-host-projection-flexibility.md","status":"accepted","created_at":"2026-05-06","updated_at":"2026-05-06"}],"decisions":[{"id":"DEC-0034","file":"DEC-0034-frontend-semantic-host-projection-flexibility.md","status":"accepted","created_at":"2026-05-06","updated_at":"2026-05-06","ref_agenda":"AGD-0037"}],"plans":[{"id":"PLN-0072","file":"PLN-0072-frontend-semantic-host-projection-contract.md","status":"done","created_at":"2026-05-06","updated_at":"2026-05-06","ref_decisions":["DEC-0034"]},{"id":"PLN-0073","file":"PLN-0073-lsp-semantic-host-projection-transport.md","status":"done","created_at":"2026-05-06","updated_at":"2026-05-06","ref_decisions":["DEC-0034"]},{"id":"PLN-0074","file":"PLN-0074-vscode-semantic-host-projection-adapter.md","status":"done","created_at":"2026-05-06","updated_at":"2026-05-06","ref_decisions":["DEC-0034"]}],"lessons":[]} {"type":"discussion","id":"DSC-0033","status":"in_progress","ticket":"frontend-visual-theme-spec-and-css-retirement","title":"Frontend visual theme spec and retirement of host-consumed semantic CSS","created_at":"2026-05-06","updated_at":"2026-05-06","tags":["compiler","compiler-general","frontend","presentation","theming","studio","vscode","lsp","pbs"],"agendas":[{"id":"AGD-0036","file":"AGD-0036-frontend-visual-theme-spec-and-css-retirement.md","status":"accepted","created_at":"2026-05-06","updated_at":"2026-05-06"}],"decisions":[{"id":"DEC-0033","file":"DEC-0033-frontend-visual-theme-spec-and-css-retirement.md","status":"accepted","created_at":"2026-05-06","updated_at":"2026-05-06","ref_agenda":"AGD-0036"}],"plans":[{"id":"PLN-0068","file":"PLN-0068-frontend-visual-contract-and-pbs-migration.md","status":"open","created_at":"2026-05-06","updated_at":"2026-05-06","ref_decisions":["DEC-0033"]},{"id":"PLN-0069","file":"PLN-0069-lsp-visual-theme-transport-and-selection.md","status":"open","created_at":"2026-05-06","updated_at":"2026-05-06","ref_decisions":["DEC-0033"]},{"id":"PLN-0070","file":"PLN-0070-studio-visual-theme-adapter-and-css-retirement.md","status":"open","created_at":"2026-05-06","updated_at":"2026-05-06","ref_decisions":["DEC-0033"]},{"id":"PLN-0071","file":"PLN-0071-vscode-dynamic-theme-translation-adapter.md","status":"open","created_at":"2026-05-06","updated_at":"2026-05-06","ref_decisions":["DEC-0033"]}],"lessons":[]} {"type":"discussion","id":"DSC-0032","status":"in_progress","ticket":"studio-new-lsp-api-and-v1-boundary","title":"Novo boundary entre lsp-api, lsp-v1 e a extensao VS Code","created_at":"2026-05-05","updated_at":"2026-05-05","tags":["studio","lsp","vscode","protocol","api","boundary"],"agendas":[{"id":"AGD-0035","file":"AGD-0035-studio-new-lsp-api-and-v1-boundary.md","status":"accepted","created_at":"2026-05-05","updated_at":"2026-05-05"}],"decisions":[{"id":"DEC-0032","file":"DEC-0032-studio-new-lsp-api-and-v1-boundary.md","status":"accepted","created_at":"2026-05-05","updated_at":"2026-05-05","ref_agenda":"AGD-0035"}],"plans":[{"id":"PLN-0065","file":"PLN-0065-lsp-boundary-and-module-scaffolding.md","status":"done","created_at":"2026-05-05","updated_at":"2026-05-05","ref_decisions":["DEC-0032"]},{"id":"PLN-0066","file":"PLN-0066-project-scoped-lsp-server-lifecycle-in-studio.md","status":"done","created_at":"2026-05-05","updated_at":"2026-05-05","ref_decisions":["DEC-0032"]},{"id":"PLN-0067","file":"PLN-0067-compiler-backed-dumb-lsp-server-baseline.md","status":"done","created_at":"2026-05-05","updated_at":"2026-05-05","ref_decisions":["DEC-0032"]}],"lessons":[]} {"type":"discussion","id":"DSC-0031","status":"in_progress","ticket":"studio-editor-workspace-cleanup","title":"Limpeza completa do Workspace Editor do Studio e remoção dos acoplamentos legados","created_at":"2026-05-05","updated_at":"2026-05-05","tags":["studio","editor","cleanup","vfs","lsp","migration"],"agendas":[{"id":"AGD-0034","file":"AGD-0034-vscode-editor-migration-feasibility.md","status":"accepted","created_at":"2026-05-05","updated_at":"2026-05-05"}],"decisions":[{"id":"DEC-0031","file":"DEC-0031-studio-editor-workspace-cleanup.md","status":"in_progress","created_at":"2026-05-05","updated_at":"2026-05-05","ref_agenda":"AGD-0034"}],"plans":[{"id":"PLN-0062","file":"PLN-0062-shell-session-and-state-cleanup-after-editor-removal.md","status":"done","created_at":"2026-05-05","updated_at":"2026-05-05","ref_decisions":["DEC-0031"]},{"id":"PLN-0063","file":"PLN-0063-legacy-lsp-and-vfs-module-removal-with-runtime-preservation.md","status":"done","created_at":"2026-05-05","updated_at":"2026-05-05","ref_decisions":["DEC-0031"]},{"id":"PLN-0064","file":"PLN-0064-normative-test-and-lesson-cleanup-for-editor-stack-removal.md","status":"done","created_at":"2026-05-05","updated_at":"2026-05-05","ref_decisions":["DEC-0031"]}],"lessons":[]} diff --git a/discussion/workflow/plans/PLN-0074-vscode-semantic-host-projection-adapter.md b/discussion/workflow/plans/PLN-0074-vscode-semantic-host-projection-adapter.md index eab87eec..53bc1fc3 100644 --- a/discussion/workflow/plans/PLN-0074-vscode-semantic-host-projection-adapter.md +++ b/discussion/workflow/plans/PLN-0074-vscode-semantic-host-projection-adapter.md @@ -2,9 +2,9 @@ id: PLN-0074 ticket: frontend-semantic-host-projection-flexibility title: VS Code Semantic Host Projection Adapter -status: open +status: done created: 2026-05-06 -completed: +completed: 2026-05-06 tags: [vscode, extension, frontend, semantics, host-projection, adapter] --- diff --git a/tools/vscode-extension/out/extension.js b/tools/vscode-extension/out/extension.js index 6e850aff..3baaba89 100644 --- a/tools/vscode-extension/out/extension.js +++ b/tools/vscode-extension/out/extension.js @@ -45,6 +45,7 @@ let reconnectContext; let stoppingClient = false; let lastAppliedThemeSignature; const RECONNECT_DELAY_MS = 2000; +const VSCODE_HOST_ID = "vscode"; function activate(context) { reconnectContext = context; output = vscode.window.createOutputChannel("Prometeu LSP"); @@ -207,21 +208,30 @@ function clearReconnectTimer() { reconnectTimer = undefined; } async function applyPrometeuVisualTheme(initializeResult) { - const payload = extractPrometeuVisualThemesPayload(initializeResult); - if (!payload) { + const visualThemesPayload = extractPrometeuVisualThemesPayload(initializeResult); + if (!visualThemesPayload) { output.appendLine("Prometeu visual theme payload not present in initialize result."); return; } - const activeTheme = payload.visualThemes.find((theme) => theme.themeId === payload.activeVisualThemeId); + const semanticProjectionPayload = extractPrometeuSemanticHostProjectionsPayload(initializeResult); + const vscodeProjection = selectHostProjection(semanticProjectionPayload, VSCODE_HOST_ID); + if (!semanticProjectionPayload) { + output.appendLine("Prometeu semantic host projection payload not present in initialize result."); + } + else if (!vscodeProjection) { + output.appendLine("Prometeu semantic host projection payload does not declare a vscode projection."); + } + const activeTheme = visualThemesPayload.visualThemes.find((theme) => theme.themeId === visualThemesPayload.activeVisualThemeId); if (!activeTheme) { - output.appendLine(`Prometeu visual theme '${payload.activeVisualThemeId}' was not declared by the server.`); + output.appendLine(`Prometeu visual theme '${visualThemesPayload.activeVisualThemeId}' was not declared by the server.`); return; } const themeSignature = JSON.stringify({ - languageId: payload.frontendLanguageId, + languageId: visualThemesPayload.frontendLanguageId, themeId: activeTheme.themeId, editorPalette: activeTheme.editorPalette, - tokenStyles: activeTheme.tokenStyles + tokenStyles: activeTheme.tokenStyles, + semanticProjection: vscodeProjection ?? null }); if (themeSignature === lastAppliedThemeSignature) { output.appendLine(`Prometeu visual theme '${activeTheme.themeId}' is already applied.`); @@ -234,7 +244,7 @@ async function applyPrometeuVisualTheme(initializeResult) { const existingSemanticCustomizations = configuration.get("editor.semanticTokenColorCustomizations") ?? {}; const semanticRules = { ...(readObject(existingSemanticCustomizations.rules)), - ...buildSemanticTokenRules(payload.frontendLanguageId, activeTheme) + ...buildSemanticTokenRules(visualThemesPayload.frontendLanguageId, activeTheme, vscodeProjection) }; await configuration.update("editor.semanticTokenColorCustomizations", { ...existingSemanticCustomizations, @@ -249,7 +259,7 @@ async function applyPrometeuVisualTheme(initializeResult) { "editorLineNumber.foreground": activeTheme.editorPalette.lineNumberForeground }, configurationTarget); lastAppliedThemeSignature = themeSignature; - output.appendLine(`Applied Prometeu visual theme '${activeTheme.themeId}' for language '${payload.frontendLanguageId}'.`); + output.appendLine(`Applied Prometeu visual theme '${activeTheme.themeId}' for language '${visualThemesPayload.frontendLanguageId}'.`); } function extractPrometeuVisualThemesPayload(initializeResult) { if (!initializeResult || typeof initializeResult !== "object") { @@ -266,27 +276,63 @@ function extractPrometeuVisualThemesPayload(initializeResult) { } return payload; } -function buildSemanticTokenRules(languageId, theme) { +function extractPrometeuSemanticHostProjectionsPayload(initializeResult) { + if (!initializeResult || typeof initializeResult !== "object") { + return undefined; + } + const capabilities = readObject(initializeResult.capabilities); + const experimental = readObject(capabilities.experimental); + const payload = readObject(experimental.prometeuSemanticHostProjections); + if (typeof payload.frontendLanguageId !== "string" || !Array.isArray(payload.semanticKeys) || !Array.isArray(payload.hostProjections)) { + return undefined; + } + return payload; +} +function selectHostProjection(payload, hostId) { + if (!payload) { + return undefined; + } + return payload.hostProjections.find((projection) => projection.hostId === hostId); +} +function buildSemanticTokenRules(languageId, theme, hostProjection) { const rules = {}; + const projectionBySemanticKey = new Map((hostProjection?.tokenProjections ?? []).map((projection) => [projection.semanticKey, projection])); for (const tokenStyle of theme.tokenStyles) { - const selector = `${tokenStyle.semanticKey}:${languageId}`; - if (!tokenStyle.italic && !tokenStyle.bold && !tokenStyle.underline) { - rules[selector] = tokenStyle.foreground; + const styleValue = !tokenStyle.italic && !tokenStyle.bold && !tokenStyle.underline + ? tokenStyle.foreground + : { + foreground: tokenStyle.foreground, + ...(tokenStyle.italic ? { italic: true } : {}), + ...(tokenStyle.bold ? { bold: true } : {}), + ...(tokenStyle.underline ? { underline: true } : {}) + }; + rules[`${tokenStyle.semanticKey}:${languageId}`] = styleValue; + const projection = projectionBySemanticKey.get(tokenStyle.semanticKey); + if (!projection) { continue; } - rules[selector] = { - foreground: tokenStyle.foreground, - ...(tokenStyle.italic ? { italic: true } : {}), - ...(tokenStyle.bold ? { bold: true } : {}), - ...(tokenStyle.underline ? { underline: true } : {}) - }; + const projectedSelector = buildSemanticSelector(languageId, projection.hostTokenType, projection.hostTokenModifiers); + if (!(projectedSelector in rules)) { + rules[projectedSelector] = styleValue; + } + const fallbackSelector = buildSemanticSelector(languageId, projection.fallbackTokenType, projection.fallbackTokenModifiers); + if (!(fallbackSelector in rules)) { + rules[fallbackSelector] = styleValue; + } } return rules; } +function buildSemanticSelector(languageId, tokenType, modifiers) { + const normalizedModifiers = [...modifiers].sort(); + if (normalizedModifiers.length === 0) { + return `${tokenType}:${languageId}`; + } + return `${tokenType}.${normalizedModifiers.join(".")}:${languageId}`; +} function readObject(value) { if (!value || typeof value !== "object" || Array.isArray(value)) { return {}; } return value; } -//# sourceMappingURL=extension.js.map \ No newline at end of file +//# sourceMappingURL=extension.js.map diff --git a/tools/vscode-extension/package.json b/tools/vscode-extension/package.json index f370837e..823a02a4 100644 --- a/tools/vscode-extension/package.json +++ b/tools/vscode-extension/package.json @@ -53,100 +53,6 @@ } } }, - "semanticTokenTypes": [ - { - "id": "pbs-comment", - "description": "PBS comment token" - }, - { - "id": "pbs-string", - "description": "PBS string token" - }, - { - "id": "pbs-number", - "description": "PBS number token" - }, - { - "id": "pbs-literal", - "description": "PBS literal token" - }, - { - "id": "pbs-lifecycle", - "description": "PBS lifecycle token" - }, - { - "id": "pbs-keyword", - "description": "PBS keyword token" - }, - { - "id": "pbs-operator", - "description": "PBS operator token" - }, - { - "id": "pbs-punctuation", - "description": "PBS punctuation token" - }, - { - "id": "pbs-function", - "description": "PBS function token" - }, - { - "id": "pbs-method", - "description": "PBS method token" - }, - { - "id": "pbs-constructor", - "description": "PBS constructor token" - }, - { - "id": "pbs-struct", - "description": "PBS struct token" - }, - { - "id": "pbs-contract", - "description": "PBS contract token" - }, - { - "id": "pbs-host", - "description": "PBS host token" - }, - { - "id": "pbs-builtin-type", - "description": "PBS builtin type token" - }, - { - "id": "pbs-service", - "description": "PBS service token" - }, - { - "id": "pbs-error", - "description": "PBS error token" - }, - { - "id": "pbs-enum", - "description": "PBS enum token" - }, - { - "id": "pbs-callback", - "description": "PBS callback token" - }, - { - "id": "pbs-global", - "description": "PBS global token" - }, - { - "id": "pbs-const", - "description": "PBS const token" - }, - { - "id": "pbs-implements", - "description": "PBS implements token" - }, - { - "id": "pbs-identifier", - "description": "PBS identifier token" - } - ], "configurationDefaults": { "editor.semanticHighlighting.enabled": true } diff --git a/tools/vscode-extension/src/extension.ts b/tools/vscode-extension/src/extension.ts index 19d7a1b5..090ae8d6 100644 --- a/tools/vscode-extension/src/extension.ts +++ b/tools/vscode-extension/src/extension.ts @@ -51,6 +51,27 @@ type PrometeuVisualThemesPayload = { visualThemes: PrometeuVisualTheme[]; }; +type PrometeuSemanticHostProjectionEntry = { + semanticKey: string; + hostTokenType: string; + hostTokenModifiers: string[]; + fallbackTokenType: string; + fallbackTokenModifiers: string[]; +}; + +type PrometeuSemanticHostProjection = { + hostId: string; + tokenProjections: PrometeuSemanticHostProjectionEntry[]; +}; + +type PrometeuSemanticHostProjectionsPayload = { + frontendLanguageId: string; + semanticKeys: string[]; + hostProjections: PrometeuSemanticHostProjection[]; +}; + +const VSCODE_HOST_ID = "vscode"; + export function activate(context: vscode.ExtensionContext): void { reconnectContext = context; output = vscode.window.createOutputChannel("Prometeu LSP"); @@ -255,23 +276,31 @@ function clearReconnectTimer(): void { } async function applyPrometeuVisualTheme(initializeResult: unknown): Promise { - const payload = extractPrometeuVisualThemesPayload(initializeResult); - if (!payload) { + const visualThemesPayload = extractPrometeuVisualThemesPayload(initializeResult); + if (!visualThemesPayload) { output.appendLine("Prometeu visual theme payload not present in initialize result."); return; } + const semanticProjectionPayload = extractPrometeuSemanticHostProjectionsPayload(initializeResult); + const vscodeProjection = selectHostProjection(semanticProjectionPayload, VSCODE_HOST_ID); + if (!semanticProjectionPayload) { + output.appendLine("Prometeu semantic host projection payload not present in initialize result."); + } else if (!vscodeProjection) { + output.appendLine("Prometeu semantic host projection payload does not declare a vscode projection."); + } - const activeTheme = payload.visualThemes.find((theme) => theme.themeId === payload.activeVisualThemeId); + const activeTheme = visualThemesPayload.visualThemes.find((theme) => theme.themeId === visualThemesPayload.activeVisualThemeId); if (!activeTheme) { - output.appendLine(`Prometeu visual theme '${payload.activeVisualThemeId}' was not declared by the server.`); + output.appendLine(`Prometeu visual theme '${visualThemesPayload.activeVisualThemeId}' was not declared by the server.`); return; } const themeSignature = JSON.stringify({ - languageId: payload.frontendLanguageId, + languageId: visualThemesPayload.frontendLanguageId, themeId: activeTheme.themeId, editorPalette: activeTheme.editorPalette, - tokenStyles: activeTheme.tokenStyles + tokenStyles: activeTheme.tokenStyles, + semanticProjection: vscodeProjection ?? null }); if (themeSignature === lastAppliedThemeSignature) { output.appendLine(`Prometeu visual theme '${activeTheme.themeId}' is already applied.`); @@ -286,7 +315,7 @@ async function applyPrometeuVisualTheme(initializeResult: unknown): Promise>("editor.semanticTokenColorCustomizations") ?? {}; const semanticRules = { ...(readObject(existingSemanticCustomizations.rules)), - ...buildSemanticTokenRules(payload.frontendLanguageId, activeTheme) + ...buildSemanticTokenRules(visualThemesPayload.frontendLanguageId, activeTheme, vscodeProjection) }; await configuration.update( @@ -312,7 +341,7 @@ async function applyPrometeuVisualTheme(initializeResult: unknown): Promise projection.hostId === hostId); +} + function buildSemanticTokenRules( languageId: string, - theme: PrometeuVisualTheme + theme: PrometeuVisualTheme, + hostProjection: PrometeuSemanticHostProjection | undefined ): Record { const rules: Record = {}; + const projectionBySemanticKey = new Map( + (hostProjection?.tokenProjections ?? []).map((projection) => [projection.semanticKey, projection]) + ); for (const tokenStyle of theme.tokenStyles) { - const selector = `${tokenStyle.semanticKey}:${languageId}`; - if (!tokenStyle.italic && !tokenStyle.bold && !tokenStyle.underline) { - rules[selector] = tokenStyle.foreground; + const styleValue = !tokenStyle.italic && !tokenStyle.bold && !tokenStyle.underline + ? tokenStyle.foreground + : { + foreground: tokenStyle.foreground, + ...(tokenStyle.italic ? { italic: true } : {}), + ...(tokenStyle.bold ? { bold: true } : {}), + ...(tokenStyle.underline ? { underline: true } : {}) + }; + rules[`${tokenStyle.semanticKey}:${languageId}`] = styleValue; + + const projection = projectionBySemanticKey.get(tokenStyle.semanticKey); + if (!projection) { continue; } - rules[selector] = { - foreground: tokenStyle.foreground, - ...(tokenStyle.italic ? { italic: true } : {}), - ...(tokenStyle.bold ? { bold: true } : {}), - ...(tokenStyle.underline ? { underline: true } : {}) - }; + + const projectedSelector = buildSemanticSelector(languageId, projection.hostTokenType, projection.hostTokenModifiers); + if (!(projectedSelector in rules)) { + rules[projectedSelector] = styleValue; + } + + const fallbackSelector = buildSemanticSelector(languageId, projection.fallbackTokenType, projection.fallbackTokenModifiers); + if (!(fallbackSelector in rules)) { + rules[fallbackSelector] = styleValue; + } } return rules; } +function buildSemanticSelector( + languageId: string, + tokenType: string, + modifiers: string[] +): string { + const normalizedModifiers = [...modifiers].sort(); + if (normalizedModifiers.length === 0) { + return `${tokenType}:${languageId}`; + } + return `${tokenType}.${normalizedModifiers.join(".")}:${languageId}`; +} + function readObject(value: unknown): Record { if (!value || typeof value !== "object" || Array.isArray(value)) { return {}; -- 2.47.2 From fb13e166f14ca6fef4718323a0542892478e218f Mon Sep 17 00:00:00 2001 From: bQUARKz Date: Wed, 6 May 2026 15:39:43 +0100 Subject: [PATCH 26/37] Frontend Visual Theme Spec and Retirement of Host-Consumed Semantic CSS --- .../p/studio/compiler/PBSDefinitions.java | 2 - .../compiler/PBSFrontendHostProjections.java | 38 +- .../FrontendSemanticPresentationSpec.java | 82 +- .../FrontendSemanticPresentationSpecTest.java | 21 +- test-projects/main/.vscode/settings.json | 29 +- .../main/assets/.prometeu/cache.json | 784 +++++++++--------- tools/vscode-extension/out/extension.js | 2 +- 7 files changed, 505 insertions(+), 453 deletions(-) diff --git a/prometeu-compiler/frontends/prometeu-frontend-pbs/src/main/java/p/studio/compiler/PBSDefinitions.java b/prometeu-compiler/frontends/prometeu-frontend-pbs/src/main/java/p/studio/compiler/PBSDefinitions.java index 4daf9129..e55a89ef 100644 --- a/prometeu-compiler/frontends/prometeu-frontend-pbs/src/main/java/p/studio/compiler/PBSDefinitions.java +++ b/prometeu-compiler/frontends/prometeu-frontend-pbs/src/main/java/p/studio/compiler/PBSDefinitions.java @@ -2,7 +2,6 @@ package p.studio.compiler; import p.studio.compiler.models.FrontendSemanticPresentationSpec; import p.studio.compiler.models.FrontendSpec; -import p.studio.compiler.pbs.PbsSemanticKind; import p.studio.utilities.structures.ReadOnlySet; import java.util.List; @@ -15,7 +14,6 @@ public class PBSDefinitions { .sourceRoots(ReadOnlySet.from("src")) .stdlibVersions(List.of(FrontendSpec.Stdlib.asDefault(1))) .semanticPresentation(new FrontendSemanticPresentationSpec( - PbsSemanticKind.semanticKeys(), List.of(PBSFrontendThemes.DEFAULT_PBS), "pbs-default", List.of(PBSFrontendHostProjections.VSCODE))) diff --git a/prometeu-compiler/frontends/prometeu-frontend-pbs/src/main/java/p/studio/compiler/PBSFrontendHostProjections.java b/prometeu-compiler/frontends/prometeu-frontend-pbs/src/main/java/p/studio/compiler/PBSFrontendHostProjections.java index 995bfeac..b73fec13 100644 --- a/prometeu-compiler/frontends/prometeu-frontend-pbs/src/main/java/p/studio/compiler/PBSFrontendHostProjections.java +++ b/prometeu-compiler/frontends/prometeu-frontend-pbs/src/main/java/p/studio/compiler/PBSFrontendHostProjections.java @@ -2,46 +2,26 @@ package p.studio.compiler; import p.studio.compiler.models.FrontendHostProjectionEntrySpec; import p.studio.compiler.models.FrontendHostProjectionSpec; +import p.studio.compiler.pbs.PbsSemanticKind; import java.util.Arrays; +import java.util.List; -import static p.studio.compiler.pbs.PbsSemanticKind.BUILTIN_TYPE; -import static p.studio.compiler.pbs.PbsSemanticKind.CALLBACK; -import static p.studio.compiler.pbs.PbsSemanticKind.COMMENT; -import static p.studio.compiler.pbs.PbsSemanticKind.CONST; -import static p.studio.compiler.pbs.PbsSemanticKind.CONSTRUCTOR; -import static p.studio.compiler.pbs.PbsSemanticKind.CONTRACT; -import static p.studio.compiler.pbs.PbsSemanticKind.ENUM; -import static p.studio.compiler.pbs.PbsSemanticKind.ERROR; -import static p.studio.compiler.pbs.PbsSemanticKind.FUNCTION; -import static p.studio.compiler.pbs.PbsSemanticKind.GLOBAL; -import static p.studio.compiler.pbs.PbsSemanticKind.HOST; -import static p.studio.compiler.pbs.PbsSemanticKind.IDENTIFIER; -import static p.studio.compiler.pbs.PbsSemanticKind.IMPLEMENTS; -import static p.studio.compiler.pbs.PbsSemanticKind.KEYWORD; -import static p.studio.compiler.pbs.PbsSemanticKind.LIFECYCLE; -import static p.studio.compiler.pbs.PbsSemanticKind.LITERAL; -import static p.studio.compiler.pbs.PbsSemanticKind.METHOD; -import static p.studio.compiler.pbs.PbsSemanticKind.NUMBER; -import static p.studio.compiler.pbs.PbsSemanticKind.OPERATOR; -import static p.studio.compiler.pbs.PbsSemanticKind.PUNCTUATION; -import static p.studio.compiler.pbs.PbsSemanticKind.SERVICE; -import static p.studio.compiler.pbs.PbsSemanticKind.STRING; -import static p.studio.compiler.pbs.PbsSemanticKind.STRUCT; +import static p.studio.compiler.pbs.PbsSemanticKind.*; public final class PBSFrontendHostProjections { public static final String VSCODE_HOST_ID = "vscode"; public static final FrontendHostProjectionSpec VSCODE = new FrontendHostProjectionSpec( VSCODE_HOST_ID, - Arrays.stream(p.studio.compiler.pbs.PbsSemanticKind.values()) + Arrays.stream(PbsSemanticKind.values()) .map(PBSFrontendHostProjections::mapVscodeProjection) .toList()); private PBSFrontendHostProjections() { } - private static FrontendHostProjectionEntrySpec mapVscodeProjection(final p.studio.compiler.pbs.PbsSemanticKind kind) { + private static FrontendHostProjectionEntrySpec mapVscodeProjection(final PbsSemanticKind kind) { return switch (kind) { case COMMENT -> projection(COMMENT.semanticKey(), "comment"); case STRING -> projection(STRING.semanticKey(), "string"); @@ -72,14 +52,14 @@ public final class PBSFrontendHostProjections { private static FrontendHostProjectionEntrySpec projection( final String semanticKey, final String hostTokenType) { - return new FrontendHostProjectionEntrySpec(semanticKey, hostTokenType, java.util.List.of(), hostTokenType, java.util.List.of()); + return new FrontendHostProjectionEntrySpec(semanticKey, hostTokenType, List.of(), hostTokenType, List.of()); } private static FrontendHostProjectionEntrySpec projection( final String semanticKey, final String hostTokenType, final String fallbackTokenType) { - return new FrontendHostProjectionEntrySpec(semanticKey, hostTokenType, java.util.List.of(), fallbackTokenType, java.util.List.of()); + return new FrontendHostProjectionEntrySpec(semanticKey, hostTokenType, List.of(), fallbackTokenType, List.of()); } private static FrontendHostProjectionEntrySpec projection( @@ -90,8 +70,8 @@ public final class PBSFrontendHostProjections { return new FrontendHostProjectionEntrySpec( semanticKey, hostTokenType, - java.util.List.of(modifier), + List.of(modifier), fallbackTokenType, - java.util.List.of(modifier)); + List.of(modifier)); } } diff --git a/prometeu-compiler/prometeu-compiler-core/src/main/java/p/studio/compiler/models/FrontendSemanticPresentationSpec.java b/prometeu-compiler/prometeu-compiler-core/src/main/java/p/studio/compiler/models/FrontendSemanticPresentationSpec.java index 5de32aa9..9a4a6309 100644 --- a/prometeu-compiler/prometeu-compiler-core/src/main/java/p/studio/compiler/models/FrontendSemanticPresentationSpec.java +++ b/prometeu-compiler/prometeu-compiler-core/src/main/java/p/studio/compiler/models/FrontendSemanticPresentationSpec.java @@ -4,57 +4,80 @@ import java.util.List; import java.util.Objects; public record FrontendSemanticPresentationSpec( - List semanticKeys, List themes, String defaultThemeId, List hostProjections) { public FrontendSemanticPresentationSpec( - final List semanticKeys, final List themes, final String defaultThemeId) { - this(semanticKeys, themes, defaultThemeId, List.of()); + this(themes, defaultThemeId, List.of()); } public FrontendSemanticPresentationSpec { - semanticKeys = List.copyOf(Objects.requireNonNull(semanticKeys, "semanticKeys")); themes = List.copyOf(Objects.requireNonNull(themes, "themes")); defaultThemeId = Objects.requireNonNull(defaultThemeId, "defaultThemeId").trim(); hostProjections = List.copyOf(Objects.requireNonNull(hostProjections, "hostProjections")); - if (semanticKeys.isEmpty() && themes.isEmpty()) { + if (themes.isEmpty()) { if (!defaultThemeId.isEmpty()) { throw new IllegalArgumentException("defaultThemeId must be blank when no themes are declared"); } + if (!hostProjections.isEmpty()) { + throw new IllegalArgumentException("hostProjections must be empty when no themes are declared"); + } } else { defaultThemeId = requireText(defaultThemeId, "defaultThemeId"); - if (themes.isEmpty()) { - throw new IllegalArgumentException("themes must not be empty"); - } - if (themes.stream().map(FrontendVisualThemeSpec::themeId).noneMatch(defaultThemeId::equals)) { + final String resolvedDefaultThemeId = defaultThemeId; + if (themes.stream().map(FrontendVisualThemeSpec::themeId).noneMatch(resolvedDefaultThemeId::equals)) { throw new IllegalArgumentException("defaultThemeId must reference one of the declared themes"); } - } - final List normalizedSemanticKeys = semanticKeys.stream() - .map(key -> requireText(key, "semanticKeys entry")) - .toList(); - final var hostIds = new java.util.LinkedHashSet(); - for (final FrontendHostProjectionSpec hostProjection : hostProjections) { - if (!hostIds.add(hostProjection.hostId())) { - throw new IllegalArgumentException("duplicate host projection for hostId: " + hostProjection.hostId()); - } - for (final FrontendHostProjectionEntrySpec tokenProjection : hostProjection.tokenProjections()) { - if (!normalizedSemanticKeys.contains(tokenProjection.semanticKey())) { + + final List derivedSemanticKeys = themes.stream() + .filter(theme -> theme.themeId().equals(resolvedDefaultThemeId)) + .findFirst() + .orElseThrow(() -> new IllegalStateException("defaultThemeId must resolve to a declared theme")) + .tokenStyles() + .stream() + .map(FrontendTokenStyleSpec::semanticKey) + .toList(); + + for (final FrontendVisualThemeSpec theme : themes) { + final List themeSemanticKeys = theme.tokenStyles().stream() + .map(FrontendTokenStyleSpec::semanticKey) + .toList(); + if (!themeSemanticKeys.equals(derivedSemanticKeys)) { throw new IllegalArgumentException( - "host projection for hostId '" + hostProjection.hostId() + "' references unknown semantic key: " - + tokenProjection.semanticKey()); + "theme '" + theme.themeId() + "' must publish the same semantic keys as the default theme"); + } + } + + final var hostIds = new java.util.LinkedHashSet(); + for (final FrontendHostProjectionSpec hostProjection : hostProjections) { + if (!hostIds.add(hostProjection.hostId())) { + throw new IllegalArgumentException( + "duplicate host projection for hostId: " + hostProjection.hostId()); + } + final List projectedSemanticKeys = hostProjection.tokenProjections().stream() + .map(FrontendHostProjectionEntrySpec::semanticKey) + .toList(); + if (!projectedSemanticKeys.equals(derivedSemanticKeys)) { + throw new IllegalArgumentException( + "host projection for hostId '" + hostProjection.hostId() + + "' must publish the same semantic keys as the default theme"); + } + for (final FrontendHostProjectionEntrySpec tokenProjection : hostProjection.tokenProjections()) { + if (!derivedSemanticKeys.contains(tokenProjection.semanticKey())) { + throw new IllegalArgumentException( + "host projection for hostId '" + hostProjection.hostId() + "' references unknown semantic key: " + + tokenProjection.semanticKey()); + } } } } - semanticKeys = normalizedSemanticKeys; } public static FrontendSemanticPresentationSpec empty() { - return new FrontendSemanticPresentationSpec(List.of(), List.of(), "", List.of()); + return new FrontendSemanticPresentationSpec(List.of(), "", List.of()); } public FrontendVisualThemeSpec defaultTheme() { @@ -68,7 +91,16 @@ public record FrontendSemanticPresentationSpec( } public boolean isEmpty() { - return semanticKeys.isEmpty() && themes.isEmpty() && defaultThemeId.isEmpty() && hostProjections.isEmpty(); + return themes.isEmpty() && defaultThemeId.isEmpty() && hostProjections.isEmpty(); + } + + public List semanticKeys() { + if (themes.isEmpty()) { + return List.of(); + } + return defaultTheme().tokenStyles().stream() + .map(FrontendTokenStyleSpec::semanticKey) + .toList(); } public java.util.Optional hostProjection(final String hostId) { diff --git a/prometeu-compiler/prometeu-compiler-core/src/test/java/p/studio/compiler/models/FrontendSemanticPresentationSpecTest.java b/prometeu-compiler/prometeu-compiler-core/src/test/java/p/studio/compiler/models/FrontendSemanticPresentationSpecTest.java index ded116dd..473facd0 100644 --- a/prometeu-compiler/prometeu-compiler-core/src/test/java/p/studio/compiler/models/FrontendSemanticPresentationSpecTest.java +++ b/prometeu-compiler/prometeu-compiler-core/src/test/java/p/studio/compiler/models/FrontendSemanticPresentationSpecTest.java @@ -12,7 +12,6 @@ final class FrontendSemanticPresentationSpecTest { @Test void shouldExposeHostProjectionByHostId() { final var presentation = new FrontendSemanticPresentationSpec( - List.of("demo-key"), List.of(new FrontendVisualThemeSpec( "demo-theme", "Demo Theme", @@ -37,7 +36,6 @@ final class FrontendSemanticPresentationSpecTest { @Test void shouldRejectDuplicateHostIds() { assertThrows(IllegalArgumentException.class, () -> new FrontendSemanticPresentationSpec( - List.of("demo-key"), List.of(new FrontendVisualThemeSpec( "demo-theme", "Demo Theme", @@ -66,7 +64,6 @@ final class FrontendSemanticPresentationSpecTest { @Test void shouldRejectProjectionForUnknownSemanticKey() { assertThrows(IllegalArgumentException.class, () -> new FrontendSemanticPresentationSpec( - List.of("demo-key"), List.of(new FrontendVisualThemeSpec( "demo-theme", "Demo Theme", @@ -82,4 +79,22 @@ final class FrontendSemanticPresentationSpecTest { "variable", List.of())))))); } + + @Test + void shouldRejectThemeSetThatDriftsFromDefaultThemeVocabulary() { + assertThrows(IllegalArgumentException.class, () -> new FrontendSemanticPresentationSpec( + List.of( + new FrontendVisualThemeSpec( + "demo-theme", + "Demo Theme", + new FrontendEditorPaletteSpec("#111111", "#eeeeee", "#333333", "#777777", "#111111", "#222222", "#eeeeee"), + List.of(new FrontendTokenStyleSpec("demo-key", "#eeeeee", false, false, false))), + new FrontendVisualThemeSpec( + "demo-theme-2", + "Demo Theme 2", + new FrontendEditorPaletteSpec("#111111", "#eeeeee", "#333333", "#777777", "#111111", "#222222", "#eeeeee"), + List.of(new FrontendTokenStyleSpec("other-key", "#eeeeee", false, false, false)))), + "demo-theme", + List.of())); + } } diff --git a/test-projects/main/.vscode/settings.json b/test-projects/main/.vscode/settings.json index 1bc56666..afd4ce90 100644 --- a/test-projects/main/.vscode/settings.json +++ b/test-projects/main/.vscode/settings.json @@ -30,7 +30,34 @@ }, "pbs-const:pbs": "#f78c6c", "pbs-implements:pbs": "#a1c181", - "pbs-identifier:pbs": "#d4d4d4" + "pbs-identifier:pbs": "#d4d4d4", + "comment:pbs": { + "foreground": "#c090b0", + "italic": true + }, + "string:pbs": "#00c088", + "number:pbs": "#ff90b0", + "enumMember:pbs": "#4fc1ff", + "variable:pbs": "#4fc1ff", + "function.async:pbs": "#ef50c0", + "variable.async:pbs": "#ef50c0", + "keyword:pbs": "#569cd6", + "operator:pbs": "#d4d4d4", + "function:pbs": "#f2c14e", + "method:pbs": "#f2c14e", + "class.declaration:pbs": "#ecdcaa", + "type.declaration:pbs": "#ecdcaa", + "struct:pbs": "#4ec9b0", + "type:pbs": "#4ec9b0", + "interface:pbs": "#78dce8", + "class.defaultLibrary:pbs": "#b7a2fa", + "type.defaultLibrary:pbs": "#b7a2fa", + "variable.defaultLibrary:pbs": "#8be9fd", + "enum:pbs": "#ff5b5b", + "variable.readonly:pbs": { + "foreground": "#f790fc", + "italic": true + } } }, "workbench.colorCustomizations": { diff --git a/test-projects/main/assets/.prometeu/cache.json b/test-projects/main/assets/.prometeu/cache.json index 0a8c0fad..7d30e3eb 100644 --- a/test-projects/main/assets/.prometeu/cache.json +++ b/test-projects/main/assets/.prometeu/cache.json @@ -24,14 +24,14 @@ "last_modified" : 1774359772403, "fingerprint" : "eeb7cc665386299403b7be1c272375d5077f3647c587f8033aa8c9275f840562", "metadata" : { + "palette" : { + "originalArgb8888" : [ -265674 ], + "convertedRgb565" : [ -122 ] + }, "tile" : { "width" : 32, "height" : 32, "paletteIndices" : "AQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAAAAAAAAAAABAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEAAAAAAAAAAAEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQAAAAAAAAAAAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAAAAAAAAAAABAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEAAAAAAAAAAAEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQAAAAAAAAAAAQEBAQEBAQEBAQEBAAAAAAAAAAAAAAAAAAAAAAAAAAABAQEBAQEBAQEBAQEAAAAAAAAAAAAAAAAAAAAAAAAAAAEBAQEBAQEBAQEBAQAAAAAAAAAAAAAAAAAAAAAAAAAAAQEBAQEBAQEBAQEBAAAAAAAAAAAAAAAAAAAAAAAAAAABAQEBAQEBAQEBAQEAAAAAAAAAAAAAAAAAAAAAAAAAAAEBAQEBAQEBAQEBAQAAAAAAAAAAAAAAAAAAAAAAAAAAAQEBAQEBAQEBAQEBAAAAAAAAAAAAAAAAAAAAAAAAAAABAQEBAQEBAQEBAQEAAAAAAAAAAAAAAAAAAAAAAAAAAAEBAQEBAQEBAQEBAQAAAAAAAAAAAAAAAAAAAQEBAQEBAQEBAQEBAQEBAQEBAAAAAAAAAAAAAAAAAAABAQEBAQEBAQEBAQEBAQEBAQEAAAAAAAAAAAAAAAAAAAEBAQEBAQEBAQEBAQEBAQEBAQAAAAAAAAAAAAAAAAAAAQEBAQEBAQEBAQEBAAAAAAAAAAAAAAAAAAAAAAAAAAABAQEBAQEBAQEBAQEAAAAAAAAAAAAAAAAAAAAAAAAAAAEBAQEBAQEBAQEBAQAAAAAAAAAAAAAAAAAAAQEBAQEBAQEBAQEBAQEBAQEBAAAAAAAAAAAAAAAAAAABAQEBAQEBAQEBAQEBAQEBAQEAAAAAAAAAAAAAAAAAAAEBAQEBAQEBAQEBAQEBAQEBAQAAAAAAAAAAAAAAAAAAAQEBAQEBAQEBAQEBAQEBAQEBAAAAAAAAAAAAAAAAAAABAQEBAQEBAQEBAQEBAQEBAQEAAAAAAAAAAAAAAAAAAAEBAQEBAQEBAQEBAQ==" - }, - "palette" : { - "originalArgb8888" : [ -265674 ], - "convertedRgb565" : [ -122 ] } }, "diagnostics" : [ ] @@ -42,14 +42,14 @@ "last_modified" : 1774359772405, "fingerprint" : "eeb7cc665386299403b7be1c272375d5077f3647c587f8033aa8c9275f840562", "metadata" : { + "palette" : { + "originalArgb8888" : [ -265674 ], + "convertedRgb565" : [ -122 ] + }, "tile" : { "width" : 32, "height" : 32, "paletteIndices" : "AQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAAAAAAAAAAABAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEAAAAAAAAAAAEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQAAAAAAAAAAAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAAAAAAAAAAABAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEAAAAAAAAAAAEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQAAAAAAAAAAAQEBAQEBAQEBAQEBAAAAAAAAAAAAAAAAAAAAAAAAAAABAQEBAQEBAQEBAQEAAAAAAAAAAAAAAAAAAAAAAAAAAAEBAQEBAQEBAQEBAQAAAAAAAAAAAAAAAAAAAAAAAAAAAQEBAQEBAQEBAQEBAAAAAAAAAAAAAAAAAAAAAAAAAAABAQEBAQEBAQEBAQEAAAAAAAAAAAAAAAAAAAAAAAAAAAEBAQEBAQEBAQEBAQAAAAAAAAAAAAAAAAAAAAAAAAAAAQEBAQEBAQEBAQEBAAAAAAAAAAAAAAAAAAAAAAAAAAABAQEBAQEBAQEBAQEAAAAAAAAAAAAAAAAAAAAAAAAAAAEBAQEBAQEBAQEBAQAAAAAAAAAAAAAAAAAAAQEBAQEBAQEBAQEBAQEBAQEBAAAAAAAAAAAAAAAAAAABAQEBAQEBAQEBAQEBAQEBAQEAAAAAAAAAAAAAAAAAAAEBAQEBAQEBAQEBAQEBAQEBAQAAAAAAAAAAAAAAAAAAAQEBAQEBAQEBAQEBAAAAAAAAAAAAAAAAAAAAAAAAAAABAQEBAQEBAQEBAQEAAAAAAAAAAAAAAAAAAAAAAAAAAAEBAQEBAQEBAQEBAQAAAAAAAAAAAAAAAAAAAQEBAQEBAQEBAQEBAQEBAQEBAAAAAAAAAAAAAAAAAAABAQEBAQEBAQEBAQEBAQEBAQEAAAAAAAAAAAAAAAAAAAEBAQEBAQEBAQEBAQEBAQEBAQAAAAAAAAAAAAAAAAAAAQEBAQEBAQEBAQEBAQEBAQEBAAAAAAAAAAAAAAAAAAABAQEBAQEBAQEBAQEBAQEBAQEAAAAAAAAAAAAAAAAAAAEBAQEBAQEBAQEBAQ==" - }, - "palette" : { - "originalArgb8888" : [ -265674 ], - "convertedRgb565" : [ -122 ] } }, "diagnostics" : [ ] @@ -60,14 +60,14 @@ "last_modified" : 1774359772406, "fingerprint" : "eeb7cc665386299403b7be1c272375d5077f3647c587f8033aa8c9275f840562", "metadata" : { + "palette" : { + "originalArgb8888" : [ -265674 ], + "convertedRgb565" : [ -122 ] + }, "tile" : { "width" : 32, "height" : 32, "paletteIndices" : "AQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAAAAAAAAAAABAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEAAAAAAAAAAAEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQAAAAAAAAAAAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAAAAAAAAAAABAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEAAAAAAAAAAAEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQAAAAAAAAAAAQEBAQEBAQEBAQEBAAAAAAAAAAAAAAAAAAAAAAAAAAABAQEBAQEBAQEBAQEAAAAAAAAAAAAAAAAAAAAAAAAAAAEBAQEBAQEBAQEBAQAAAAAAAAAAAAAAAAAAAAAAAAAAAQEBAQEBAQEBAQEBAAAAAAAAAAAAAAAAAAAAAAAAAAABAQEBAQEBAQEBAQEAAAAAAAAAAAAAAAAAAAAAAAAAAAEBAQEBAQEBAQEBAQAAAAAAAAAAAAAAAAAAAAAAAAAAAQEBAQEBAQEBAQEBAAAAAAAAAAAAAAAAAAAAAAAAAAABAQEBAQEBAQEBAQEAAAAAAAAAAAAAAAAAAAAAAAAAAAEBAQEBAQEBAQEBAQAAAAAAAAAAAAAAAAAAAQEBAQEBAQEBAQEBAQEBAQEBAAAAAAAAAAAAAAAAAAABAQEBAQEBAQEBAQEBAQEBAQEAAAAAAAAAAAAAAAAAAAEBAQEBAQEBAQEBAQEBAQEBAQAAAAAAAAAAAAAAAAAAAQEBAQEBAQEBAQEBAAAAAAAAAAAAAAAAAAAAAAAAAAABAQEBAQEBAQEBAQEAAAAAAAAAAAAAAAAAAAAAAAAAAAEBAQEBAQEBAQEBAQAAAAAAAAAAAAAAAAAAAQEBAQEBAQEBAQEBAQEBAQEBAAAAAAAAAAAAAAAAAAABAQEBAQEBAQEBAQEBAQEBAQEAAAAAAAAAAAAAAAAAAAEBAQEBAQEBAQEBAQEBAQEBAQAAAAAAAAAAAAAAAAAAAQEBAQEBAQEBAQEBAQEBAQEBAAAAAAAAAAAAAAAAAAABAQEBAQEBAQEBAQEBAQEBAQEAAAAAAAAAAAAAAAAAAAEBAQEBAQEBAQEBAQ==" - }, - "palette" : { - "originalArgb8888" : [ -265674 ], - "convertedRgb565" : [ -122 ] } }, "diagnostics" : [ ] @@ -78,14 +78,14 @@ "last_modified" : 1774359772408, "fingerprint" : "eeb7cc665386299403b7be1c272375d5077f3647c587f8033aa8c9275f840562", "metadata" : { + "palette" : { + "originalArgb8888" : [ -265674 ], + "convertedRgb565" : [ -122 ] + }, "tile" : { "width" : 32, "height" : 32, "paletteIndices" : "AQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAAAAAAAAAAABAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEAAAAAAAAAAAEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQAAAAAAAAAAAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAAAAAAAAAAABAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEAAAAAAAAAAAEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQAAAAAAAAAAAQEBAQEBAQEBAQEBAAAAAAAAAAAAAAAAAAAAAAAAAAABAQEBAQEBAQEBAQEAAAAAAAAAAAAAAAAAAAAAAAAAAAEBAQEBAQEBAQEBAQAAAAAAAAAAAAAAAAAAAAAAAAAAAQEBAQEBAQEBAQEBAAAAAAAAAAAAAAAAAAAAAAAAAAABAQEBAQEBAQEBAQEAAAAAAAAAAAAAAAAAAAAAAAAAAAEBAQEBAQEBAQEBAQAAAAAAAAAAAAAAAAAAAAAAAAAAAQEBAQEBAQEBAQEBAAAAAAAAAAAAAAAAAAAAAAAAAAABAQEBAQEBAQEBAQEAAAAAAAAAAAAAAAAAAAAAAAAAAAEBAQEBAQEBAQEBAQAAAAAAAAAAAAAAAAAAAQEBAQEBAQEBAQEBAQEBAQEBAAAAAAAAAAAAAAAAAAABAQEBAQEBAQEBAQEBAQEBAQEAAAAAAAAAAAAAAAAAAAEBAQEBAQEBAQEBAQEBAQEBAQAAAAAAAAAAAAAAAAAAAQEBAQEBAQEBAQEBAAAAAAAAAAAAAAAAAAAAAAAAAAABAQEBAQEBAQEBAQEAAAAAAAAAAAAAAAAAAAAAAAAAAAEBAQEBAQEBAQEBAQAAAAAAAAAAAAAAAAAAAQEBAQEBAQEBAQEBAQEBAQEBAAAAAAAAAAAAAAAAAAABAQEBAQEBAQEBAQEBAQEBAQEAAAAAAAAAAAAAAAAAAAEBAQEBAQEBAQEBAQEBAQEBAQAAAAAAAAAAAAAAAAAAAQEBAQEBAQEBAQEBAQEBAQEBAAAAAAAAAAAAAAAAAAABAQEBAQEBAQEBAQEBAQEBAQEAAAAAAAAAAAAAAAAAAAEBAQEBAQEBAQEBAQ==" - }, - "palette" : { - "originalArgb8888" : [ -265674 ], - "convertedRgb565" : [ -122 ] } }, "diagnostics" : [ ] @@ -96,14 +96,14 @@ "last_modified" : 1774359772409, "fingerprint" : "eeb7cc665386299403b7be1c272375d5077f3647c587f8033aa8c9275f840562", "metadata" : { + "palette" : { + "originalArgb8888" : [ -265674 ], + "convertedRgb565" : [ -122 ] + }, "tile" : { "width" : 32, "height" : 32, "paletteIndices" : "AQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAAAAAAAAAAABAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEAAAAAAAAAAAEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQAAAAAAAAAAAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAAAAAAAAAAABAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEAAAAAAAAAAAEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQAAAAAAAAAAAQEBAQEBAQEBAQEBAAAAAAAAAAAAAAAAAAAAAAAAAAABAQEBAQEBAQEBAQEAAAAAAAAAAAAAAAAAAAAAAAAAAAEBAQEBAQEBAQEBAQAAAAAAAAAAAAAAAAAAAAAAAAAAAQEBAQEBAQEBAQEBAAAAAAAAAAAAAAAAAAAAAAAAAAABAQEBAQEBAQEBAQEAAAAAAAAAAAAAAAAAAAAAAAAAAAEBAQEBAQEBAQEBAQAAAAAAAAAAAAAAAAAAAAAAAAAAAQEBAQEBAQEBAQEBAAAAAAAAAAAAAAAAAAAAAAAAAAABAQEBAQEBAQEBAQEAAAAAAAAAAAAAAAAAAAAAAAAAAAEBAQEBAQEBAQEBAQAAAAAAAAAAAAAAAAAAAQEBAQEBAQEBAQEBAQEBAQEBAAAAAAAAAAAAAAAAAAABAQEBAQEBAQEBAQEBAQEBAQEAAAAAAAAAAAAAAAAAAAEBAQEBAQEBAQEBAQEBAQEBAQAAAAAAAAAAAAAAAAAAAQEBAQEBAQEBAQEBAAAAAAAAAAAAAAAAAAAAAAAAAAABAQEBAQEBAQEBAQEAAAAAAAAAAAAAAAAAAAAAAAAAAAEBAQEBAQEBAQEBAQAAAAAAAAAAAAAAAAAAAQEBAQEBAQEBAQEBAQEBAQEBAAAAAAAAAAAAAAAAAAABAQEBAQEBAQEBAQEBAQEBAQEAAAAAAAAAAAAAAAAAAAEBAQEBAQEBAQEBAQEBAQEBAQAAAAAAAAAAAAAAAAAAAQEBAQEBAQEBAQEBAQEBAQEBAAAAAAAAAAAAAAAAAAABAQEBAQEBAQEBAQEBAQEBAQEAAAAAAAAAAAAAAAAAAAEBAQEBAQEBAQEBAQ==" - }, - "palette" : { - "originalArgb8888" : [ -265674 ], - "convertedRgb565" : [ -122 ] } }, "diagnostics" : [ ] @@ -114,14 +114,14 @@ "last_modified" : 1774359772411, "fingerprint" : "eeb7cc665386299403b7be1c272375d5077f3647c587f8033aa8c9275f840562", "metadata" : { + "palette" : { + "originalArgb8888" : [ -265674 ], + "convertedRgb565" : [ -122 ] + }, "tile" : { "width" : 32, "height" : 32, "paletteIndices" : "AQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAAAAAAAAAAABAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEAAAAAAAAAAAEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQAAAAAAAAAAAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAAAAAAAAAAABAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEAAAAAAAAAAAEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQAAAAAAAAAAAQEBAQEBAQEBAQEBAAAAAAAAAAAAAAAAAAAAAAAAAAABAQEBAQEBAQEBAQEAAAAAAAAAAAAAAAAAAAAAAAAAAAEBAQEBAQEBAQEBAQAAAAAAAAAAAAAAAAAAAAAAAAAAAQEBAQEBAQEBAQEBAAAAAAAAAAAAAAAAAAAAAAAAAAABAQEBAQEBAQEBAQEAAAAAAAAAAAAAAAAAAAAAAAAAAAEBAQEBAQEBAQEBAQAAAAAAAAAAAAAAAAAAAAAAAAAAAQEBAQEBAQEBAQEBAAAAAAAAAAAAAAAAAAAAAAAAAAABAQEBAQEBAQEBAQEAAAAAAAAAAAAAAAAAAAAAAAAAAAEBAQEBAQEBAQEBAQAAAAAAAAAAAAAAAAAAAQEBAQEBAQEBAQEBAQEBAQEBAAAAAAAAAAAAAAAAAAABAQEBAQEBAQEBAQEBAQEBAQEAAAAAAAAAAAAAAAAAAAEBAQEBAQEBAQEBAQEBAQEBAQAAAAAAAAAAAAAAAAAAAQEBAQEBAQEBAQEBAAAAAAAAAAAAAAAAAAAAAAAAAAABAQEBAQEBAQEBAQEAAAAAAAAAAAAAAAAAAAAAAAAAAAEBAQEBAQEBAQEBAQAAAAAAAAAAAAAAAAAAAQEBAQEBAQEBAQEBAQEBAQEBAAAAAAAAAAAAAAAAAAABAQEBAQEBAQEBAQEBAQEBAQEAAAAAAAAAAAAAAAAAAAEBAQEBAQEBAQEBAQEBAQEBAQAAAAAAAAAAAAAAAAAAAQEBAQEBAQEBAQEBAQEBAQEBAAAAAAAAAAAAAAAAAAABAQEBAQEBAQEBAQEBAQEBAQEAAAAAAAAAAAAAAAAAAAEBAQEBAQEBAQEBAQ==" - }, - "palette" : { - "originalArgb8888" : [ -265674 ], - "convertedRgb565" : [ -122 ] } }, "diagnostics" : [ ] @@ -132,14 +132,14 @@ "last_modified" : 1774359772412, "fingerprint" : "eeb7cc665386299403b7be1c272375d5077f3647c587f8033aa8c9275f840562", "metadata" : { + "palette" : { + "originalArgb8888" : [ -265674 ], + "convertedRgb565" : [ -122 ] + }, "tile" : { "width" : 32, "height" : 32, "paletteIndices" : "AQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAAAAAAAAAAABAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEAAAAAAAAAAAEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQAAAAAAAAAAAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAAAAAAAAAAABAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEAAAAAAAAAAAEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQAAAAAAAAAAAQEBAQEBAQEBAQEBAAAAAAAAAAAAAAAAAAAAAAAAAAABAQEBAQEBAQEBAQEAAAAAAAAAAAAAAAAAAAAAAAAAAAEBAQEBAQEBAQEBAQAAAAAAAAAAAAAAAAAAAAAAAAAAAQEBAQEBAQEBAQEBAAAAAAAAAAAAAAAAAAAAAAAAAAABAQEBAQEBAQEBAQEAAAAAAAAAAAAAAAAAAAAAAAAAAAEBAQEBAQEBAQEBAQAAAAAAAAAAAAAAAAAAAAAAAAAAAQEBAQEBAQEBAQEBAAAAAAAAAAAAAAAAAAAAAAAAAAABAQEBAQEBAQEBAQEAAAAAAAAAAAAAAAAAAAAAAAAAAAEBAQEBAQEBAQEBAQAAAAAAAAAAAAAAAAAAAQEBAQEBAQEBAQEBAQEBAQEBAAAAAAAAAAAAAAAAAAABAQEBAQEBAQEBAQEBAQEBAQEAAAAAAAAAAAAAAAAAAAEBAQEBAQEBAQEBAQEBAQEBAQAAAAAAAAAAAAAAAAAAAQEBAQEBAQEBAQEBAAAAAAAAAAAAAAAAAAAAAAAAAAABAQEBAQEBAQEBAQEAAAAAAAAAAAAAAAAAAAAAAAAAAAEBAQEBAQEBAQEBAQAAAAAAAAAAAAAAAAAAAQEBAQEBAQEBAQEBAQEBAQEBAAAAAAAAAAAAAAAAAAABAQEBAQEBAQEBAQEBAQEBAQEAAAAAAAAAAAAAAAAAAAEBAQEBAQEBAQEBAQEBAQEBAQAAAAAAAAAAAAAAAAAAAQEBAQEBAQEBAQEBAQEBAQEBAAAAAAAAAAAAAAAAAAABAQEBAQEBAQEBAQEBAQEBAQEAAAAAAAAAAAAAAAAAAAEBAQEBAQEBAQEBAQ==" - }, - "palette" : { - "originalArgb8888" : [ -265674 ], - "convertedRgb565" : [ -122 ] } }, "diagnostics" : [ ] @@ -150,14 +150,14 @@ "last_modified" : 1774359772413, "fingerprint" : "eeb7cc665386299403b7be1c272375d5077f3647c587f8033aa8c9275f840562", "metadata" : { + "palette" : { + "originalArgb8888" : [ -265674 ], + "convertedRgb565" : [ -122 ] + }, "tile" : { "width" : 32, "height" : 32, "paletteIndices" : "AQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAAAAAAAAAAABAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEAAAAAAAAAAAEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQAAAAAAAAAAAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAAAAAAAAAAABAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEAAAAAAAAAAAEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQAAAAAAAAAAAQEBAQEBAQEBAQEBAAAAAAAAAAAAAAAAAAAAAAAAAAABAQEBAQEBAQEBAQEAAAAAAAAAAAAAAAAAAAAAAAAAAAEBAQEBAQEBAQEBAQAAAAAAAAAAAAAAAAAAAAAAAAAAAQEBAQEBAQEBAQEBAAAAAAAAAAAAAAAAAAAAAAAAAAABAQEBAQEBAQEBAQEAAAAAAAAAAAAAAAAAAAAAAAAAAAEBAQEBAQEBAQEBAQAAAAAAAAAAAAAAAAAAAAAAAAAAAQEBAQEBAQEBAQEBAAAAAAAAAAAAAAAAAAAAAAAAAAABAQEBAQEBAQEBAQEAAAAAAAAAAAAAAAAAAAAAAAAAAAEBAQEBAQEBAQEBAQAAAAAAAAAAAAAAAAAAAQEBAQEBAQEBAQEBAQEBAQEBAAAAAAAAAAAAAAAAAAABAQEBAQEBAQEBAQEBAQEBAQEAAAAAAAAAAAAAAAAAAAEBAQEBAQEBAQEBAQEBAQEBAQAAAAAAAAAAAAAAAAAAAQEBAQEBAQEBAQEBAAAAAAAAAAAAAAAAAAAAAAAAAAABAQEBAQEBAQEBAQEAAAAAAAAAAAAAAAAAAAAAAAAAAAEBAQEBAQEBAQEBAQAAAAAAAAAAAAAAAAAAAQEBAQEBAQEBAQEBAQEBAQEBAAAAAAAAAAAAAAAAAAABAQEBAQEBAQEBAQEBAQEBAQEAAAAAAAAAAAAAAAAAAAEBAQEBAQEBAQEBAQEBAQEBAQAAAAAAAAAAAAAAAAAAAQEBAQEBAQEBAQEBAQEBAQEBAAAAAAAAAAAAAAAAAAABAQEBAQEBAQEBAQEBAQEBAQEAAAAAAAAAAAAAAAAAAAEBAQEBAQEBAQEBAQ==" - }, - "palette" : { - "originalArgb8888" : [ -265674 ], - "convertedRgb565" : [ -122 ] } }, "diagnostics" : [ ] @@ -168,14 +168,14 @@ "last_modified" : 1774359772415, "fingerprint" : "eeb7cc665386299403b7be1c272375d5077f3647c587f8033aa8c9275f840562", "metadata" : { + "palette" : { + "originalArgb8888" : [ -265674 ], + "convertedRgb565" : [ -122 ] + }, "tile" : { "width" : 32, "height" : 32, "paletteIndices" : "AQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAAAAAAAAAAABAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEAAAAAAAAAAAEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQAAAAAAAAAAAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAAAAAAAAAAABAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEAAAAAAAAAAAEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQAAAAAAAAAAAQEBAQEBAQEBAQEBAAAAAAAAAAAAAAAAAAAAAAAAAAABAQEBAQEBAQEBAQEAAAAAAAAAAAAAAAAAAAAAAAAAAAEBAQEBAQEBAQEBAQAAAAAAAAAAAAAAAAAAAAAAAAAAAQEBAQEBAQEBAQEBAAAAAAAAAAAAAAAAAAAAAAAAAAABAQEBAQEBAQEBAQEAAAAAAAAAAAAAAAAAAAAAAAAAAAEBAQEBAQEBAQEBAQAAAAAAAAAAAAAAAAAAAAAAAAAAAQEBAQEBAQEBAQEBAAAAAAAAAAAAAAAAAAAAAAAAAAABAQEBAQEBAQEBAQEAAAAAAAAAAAAAAAAAAAAAAAAAAAEBAQEBAQEBAQEBAQAAAAAAAAAAAAAAAAAAAQEBAQEBAQEBAQEBAQEBAQEBAAAAAAAAAAAAAAAAAAABAQEBAQEBAQEBAQEBAQEBAQEAAAAAAAAAAAAAAAAAAAEBAQEBAQEBAQEBAQEBAQEBAQAAAAAAAAAAAAAAAAAAAQEBAQEBAQEBAQEBAAAAAAAAAAAAAAAAAAAAAAAAAAABAQEBAQEBAQEBAQEAAAAAAAAAAAAAAAAAAAAAAAAAAAEBAQEBAQEBAQEBAQAAAAAAAAAAAAAAAAAAAQEBAQEBAQEBAQEBAQEBAQEBAAAAAAAAAAAAAAAAAAABAQEBAQEBAQEBAQEBAQEBAQEAAAAAAAAAAAAAAAAAAAEBAQEBAQEBAQEBAQEBAQEBAQAAAAAAAAAAAAAAAAAAAQEBAQEBAQEBAQEBAQEBAQEBAAAAAAAAAAAAAAAAAAABAQEBAQEBAQEBAQEBAQEBAQEAAAAAAAAAAAAAAAAAAAEBAQEBAQEBAQEBAQ==" - }, - "palette" : { - "originalArgb8888" : [ -265674 ], - "convertedRgb565" : [ -122 ] } }, "diagnostics" : [ ] @@ -186,14 +186,14 @@ "last_modified" : 1774359772416, "fingerprint" : "eeb7cc665386299403b7be1c272375d5077f3647c587f8033aa8c9275f840562", "metadata" : { + "palette" : { + "originalArgb8888" : [ -265674 ], + "convertedRgb565" : [ -122 ] + }, "tile" : { "width" : 32, "height" : 32, "paletteIndices" : "AQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAAAAAAAAAAABAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEAAAAAAAAAAAEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQAAAAAAAAAAAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAAAAAAAAAAABAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEAAAAAAAAAAAEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQAAAAAAAAAAAQEBAQEBAQEBAQEBAAAAAAAAAAAAAAAAAAAAAAAAAAABAQEBAQEBAQEBAQEAAAAAAAAAAAAAAAAAAAAAAAAAAAEBAQEBAQEBAQEBAQAAAAAAAAAAAAAAAAAAAAAAAAAAAQEBAQEBAQEBAQEBAAAAAAAAAAAAAAAAAAAAAAAAAAABAQEBAQEBAQEBAQEAAAAAAAAAAAAAAAAAAAAAAAAAAAEBAQEBAQEBAQEBAQAAAAAAAAAAAAAAAAAAAAAAAAAAAQEBAQEBAQEBAQEBAAAAAAAAAAAAAAAAAAAAAAAAAAABAQEBAQEBAQEBAQEAAAAAAAAAAAAAAAAAAAAAAAAAAAEBAQEBAQEBAQEBAQAAAAAAAAAAAAAAAAAAAQEBAQEBAQEBAQEBAQEBAQEBAAAAAAAAAAAAAAAAAAABAQEBAQEBAQEBAQEBAQEBAQEAAAAAAAAAAAAAAAAAAAEBAQEBAQEBAQEBAQEBAQEBAQAAAAAAAAAAAAAAAAAAAQEBAQEBAQEBAQEBAAAAAAAAAAAAAAAAAAAAAAAAAAABAQEBAQEBAQEBAQEAAAAAAAAAAAAAAAAAAAAAAAAAAAEBAQEBAQEBAQEBAQAAAAAAAAAAAAAAAAAAAQEBAQEBAQEBAQEBAQEBAQEBAAAAAAAAAAAAAAAAAAABAQEBAQEBAQEBAQEBAQEBAQEAAAAAAAAAAAAAAAAAAAEBAQEBAQEBAQEBAQEBAQEBAQAAAAAAAAAAAAAAAAAAAQEBAQEBAQEBAQEBAQEBAQEBAAAAAAAAAAAAAAAAAAABAQEBAQEBAQEBAQEBAQEBAQEAAAAAAAAAAAAAAAAAAAEBAQEBAQEBAQEBAQ==" - }, - "palette" : { - "originalArgb8888" : [ -265674 ], - "convertedRgb565" : [ -122 ] } }, "diagnostics" : [ ] @@ -204,14 +204,14 @@ "last_modified" : 1774359772417, "fingerprint" : "eeb7cc665386299403b7be1c272375d5077f3647c587f8033aa8c9275f840562", "metadata" : { + "palette" : { + "originalArgb8888" : [ -265674 ], + "convertedRgb565" : [ -122 ] + }, "tile" : { "width" : 32, "height" : 32, "paletteIndices" : "AQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAAAAAAAAAAABAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEAAAAAAAAAAAEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQAAAAAAAAAAAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAAAAAAAAAAABAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEAAAAAAAAAAAEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQAAAAAAAAAAAQEBAQEBAQEBAQEBAAAAAAAAAAAAAAAAAAAAAAAAAAABAQEBAQEBAQEBAQEAAAAAAAAAAAAAAAAAAAAAAAAAAAEBAQEBAQEBAQEBAQAAAAAAAAAAAAAAAAAAAAAAAAAAAQEBAQEBAQEBAQEBAAAAAAAAAAAAAAAAAAAAAAAAAAABAQEBAQEBAQEBAQEAAAAAAAAAAAAAAAAAAAAAAAAAAAEBAQEBAQEBAQEBAQAAAAAAAAAAAAAAAAAAAAAAAAAAAQEBAQEBAQEBAQEBAAAAAAAAAAAAAAAAAAAAAAAAAAABAQEBAQEBAQEBAQEAAAAAAAAAAAAAAAAAAAAAAAAAAAEBAQEBAQEBAQEBAQAAAAAAAAAAAAAAAAAAAQEBAQEBAQEBAQEBAQEBAQEBAAAAAAAAAAAAAAAAAAABAQEBAQEBAQEBAQEBAQEBAQEAAAAAAAAAAAAAAAAAAAEBAQEBAQEBAQEBAQEBAQEBAQAAAAAAAAAAAAAAAAAAAQEBAQEBAQEBAQEBAAAAAAAAAAAAAAAAAAAAAAAAAAABAQEBAQEBAQEBAQEAAAAAAAAAAAAAAAAAAAAAAAAAAAEBAQEBAQEBAQEBAQAAAAAAAAAAAAAAAAAAAQEBAQEBAQEBAQEBAQEBAQEBAAAAAAAAAAAAAAAAAAABAQEBAQEBAQEBAQEBAQEBAQEAAAAAAAAAAAAAAAAAAAEBAQEBAQEBAQEBAQEBAQEBAQAAAAAAAAAAAAAAAAAAAQEBAQEBAQEBAQEBAQEBAQEBAAAAAAAAAAAAAAAAAAABAQEBAQEBAQEBAQEBAQEBAQEAAAAAAAAAAAAAAAAAAAEBAQEBAQEBAQEBAQ==" - }, - "palette" : { - "originalArgb8888" : [ -265674 ], - "convertedRgb565" : [ -122 ] } }, "diagnostics" : [ ] @@ -222,14 +222,14 @@ "last_modified" : 1774359772418, "fingerprint" : "eeb7cc665386299403b7be1c272375d5077f3647c587f8033aa8c9275f840562", "metadata" : { + "palette" : { + "originalArgb8888" : [ -265674 ], + "convertedRgb565" : [ -122 ] + }, "tile" : { "width" : 32, "height" : 32, "paletteIndices" : "AQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAAAAAAAAAAABAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEAAAAAAAAAAAEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQAAAAAAAAAAAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAAAAAAAAAAABAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEAAAAAAAAAAAEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQAAAAAAAAAAAQEBAQEBAQEBAQEBAAAAAAAAAAAAAAAAAAAAAAAAAAABAQEBAQEBAQEBAQEAAAAAAAAAAAAAAAAAAAAAAAAAAAEBAQEBAQEBAQEBAQAAAAAAAAAAAAAAAAAAAAAAAAAAAQEBAQEBAQEBAQEBAAAAAAAAAAAAAAAAAAAAAAAAAAABAQEBAQEBAQEBAQEAAAAAAAAAAAAAAAAAAAAAAAAAAAEBAQEBAQEBAQEBAQAAAAAAAAAAAAAAAAAAAAAAAAAAAQEBAQEBAQEBAQEBAAAAAAAAAAAAAAAAAAAAAAAAAAABAQEBAQEBAQEBAQEAAAAAAAAAAAAAAAAAAAAAAAAAAAEBAQEBAQEBAQEBAQAAAAAAAAAAAAAAAAAAAQEBAQEBAQEBAQEBAQEBAQEBAAAAAAAAAAAAAAAAAAABAQEBAQEBAQEBAQEBAQEBAQEAAAAAAAAAAAAAAAAAAAEBAQEBAQEBAQEBAQEBAQEBAQAAAAAAAAAAAAAAAAAAAQEBAQEBAQEBAQEBAAAAAAAAAAAAAAAAAAAAAAAAAAABAQEBAQEBAQEBAQEAAAAAAAAAAAAAAAAAAAAAAAAAAAEBAQEBAQEBAQEBAQAAAAAAAAAAAAAAAAAAAQEBAQEBAQEBAQEBAQEBAQEBAAAAAAAAAAAAAAAAAAABAQEBAQEBAQEBAQEBAQEBAQEAAAAAAAAAAAAAAAAAAAEBAQEBAQEBAQEBAQEBAQEBAQAAAAAAAAAAAAAAAAAAAQEBAQEBAQEBAQEBAQEBAQEBAAAAAAAAAAAAAAAAAAABAQEBAQEBAQEBAQEBAQEBAQEAAAAAAAAAAAAAAAAAAAEBAQEBAQEBAQEBAQ==" - }, - "palette" : { - "originalArgb8888" : [ -265674 ], - "convertedRgb565" : [ -122 ] } }, "diagnostics" : [ ] @@ -240,14 +240,14 @@ "last_modified" : 1774359772420, "fingerprint" : "eeb7cc665386299403b7be1c272375d5077f3647c587f8033aa8c9275f840562", "metadata" : { + "palette" : { + "originalArgb8888" : [ -265674 ], + "convertedRgb565" : [ -122 ] + }, "tile" : { "width" : 32, "height" : 32, "paletteIndices" : "AQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAAAAAAAAAAABAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEAAAAAAAAAAAEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQAAAAAAAAAAAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAAAAAAAAAAABAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEAAAAAAAAAAAEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQAAAAAAAAAAAQEBAQEBAQEBAQEBAAAAAAAAAAAAAAAAAAAAAAAAAAABAQEBAQEBAQEBAQEAAAAAAAAAAAAAAAAAAAAAAAAAAAEBAQEBAQEBAQEBAQAAAAAAAAAAAAAAAAAAAAAAAAAAAQEBAQEBAQEBAQEBAAAAAAAAAAAAAAAAAAAAAAAAAAABAQEBAQEBAQEBAQEAAAAAAAAAAAAAAAAAAAAAAAAAAAEBAQEBAQEBAQEBAQAAAAAAAAAAAAAAAAAAAAAAAAAAAQEBAQEBAQEBAQEBAAAAAAAAAAAAAAAAAAAAAAAAAAABAQEBAQEBAQEBAQEAAAAAAAAAAAAAAAAAAAAAAAAAAAEBAQEBAQEBAQEBAQAAAAAAAAAAAAAAAAAAAQEBAQEBAQEBAQEBAQEBAQEBAAAAAAAAAAAAAAAAAAABAQEBAQEBAQEBAQEBAQEBAQEAAAAAAAAAAAAAAAAAAAEBAQEBAQEBAQEBAQEBAQEBAQAAAAAAAAAAAAAAAAAAAQEBAQEBAQEBAQEBAAAAAAAAAAAAAAAAAAAAAAAAAAABAQEBAQEBAQEBAQEAAAAAAAAAAAAAAAAAAAAAAAAAAAEBAQEBAQEBAQEBAQAAAAAAAAAAAAAAAAAAAQEBAQEBAQEBAQEBAQEBAQEBAAAAAAAAAAAAAAAAAAABAQEBAQEBAQEBAQEBAQEBAQEAAAAAAAAAAAAAAAAAAAEBAQEBAQEBAQEBAQEBAQEBAQAAAAAAAAAAAAAAAAAAAQEBAQEBAQEBAQEBAQEBAQEBAAAAAAAAAAAAAAAAAAABAQEBAQEBAQEBAQEBAQEBAQEAAAAAAAAAAAAAAAAAAAEBAQEBAQEBAQEBAQ==" - }, - "palette" : { - "originalArgb8888" : [ -265674 ], - "convertedRgb565" : [ -122 ] } }, "diagnostics" : [ ] @@ -258,14 +258,14 @@ "last_modified" : 1774359772421, "fingerprint" : "eeb7cc665386299403b7be1c272375d5077f3647c587f8033aa8c9275f840562", "metadata" : { + "palette" : { + "originalArgb8888" : [ -265674 ], + "convertedRgb565" : [ -122 ] + }, "tile" : { "width" : 32, "height" : 32, "paletteIndices" : "AQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAAAAAAAAAAABAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEAAAAAAAAAAAEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQAAAAAAAAAAAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAAAAAAAAAAABAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEAAAAAAAAAAAEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQAAAAAAAAAAAQEBAQEBAQEBAQEBAAAAAAAAAAAAAAAAAAAAAAAAAAABAQEBAQEBAQEBAQEAAAAAAAAAAAAAAAAAAAAAAAAAAAEBAQEBAQEBAQEBAQAAAAAAAAAAAAAAAAAAAAAAAAAAAQEBAQEBAQEBAQEBAAAAAAAAAAAAAAAAAAAAAAAAAAABAQEBAQEBAQEBAQEAAAAAAAAAAAAAAAAAAAAAAAAAAAEBAQEBAQEBAQEBAQAAAAAAAAAAAAAAAAAAAAAAAAAAAQEBAQEBAQEBAQEBAAAAAAAAAAAAAAAAAAAAAAAAAAABAQEBAQEBAQEBAQEAAAAAAAAAAAAAAAAAAAAAAAAAAAEBAQEBAQEBAQEBAQAAAAAAAAAAAAAAAAAAAQEBAQEBAQEBAQEBAQEBAQEBAAAAAAAAAAAAAAAAAAABAQEBAQEBAQEBAQEBAQEBAQEAAAAAAAAAAAAAAAAAAAEBAQEBAQEBAQEBAQEBAQEBAQAAAAAAAAAAAAAAAAAAAQEBAQEBAQEBAQEBAAAAAAAAAAAAAAAAAAAAAAAAAAABAQEBAQEBAQEBAQEAAAAAAAAAAAAAAAAAAAAAAAAAAAEBAQEBAQEBAQEBAQAAAAAAAAAAAAAAAAAAAQEBAQEBAQEBAQEBAQEBAQEBAAAAAAAAAAAAAAAAAAABAQEBAQEBAQEBAQEBAQEBAQEAAAAAAAAAAAAAAAAAAAEBAQEBAQEBAQEBAQEBAQEBAQAAAAAAAAAAAAAAAAAAAQEBAQEBAQEBAQEBAQEBAQEBAAAAAAAAAAAAAAAAAAABAQEBAQEBAQEBAQEBAQEBAQEAAAAAAAAAAAAAAAAAAAEBAQEBAQEBAQEBAQ==" - }, - "palette" : { - "originalArgb8888" : [ -265674 ], - "convertedRgb565" : [ -122 ] } }, "diagnostics" : [ ] @@ -276,14 +276,14 @@ "last_modified" : 1774359772423, "fingerprint" : "eeb7cc665386299403b7be1c272375d5077f3647c587f8033aa8c9275f840562", "metadata" : { + "palette" : { + "originalArgb8888" : [ -265674 ], + "convertedRgb565" : [ -122 ] + }, "tile" : { "width" : 32, "height" : 32, "paletteIndices" : "AQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAAAAAAAAAAABAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEAAAAAAAAAAAEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQAAAAAAAAAAAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAAAAAAAAAAABAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEAAAAAAAAAAAEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQAAAAAAAAAAAQEBAQEBAQEBAQEBAAAAAAAAAAAAAAAAAAAAAAAAAAABAQEBAQEBAQEBAQEAAAAAAAAAAAAAAAAAAAAAAAAAAAEBAQEBAQEBAQEBAQAAAAAAAAAAAAAAAAAAAAAAAAAAAQEBAQEBAQEBAQEBAAAAAAAAAAAAAAAAAAAAAAAAAAABAQEBAQEBAQEBAQEAAAAAAAAAAAAAAAAAAAAAAAAAAAEBAQEBAQEBAQEBAQAAAAAAAAAAAAAAAAAAAAAAAAAAAQEBAQEBAQEBAQEBAAAAAAAAAAAAAAAAAAAAAAAAAAABAQEBAQEBAQEBAQEAAAAAAAAAAAAAAAAAAAAAAAAAAAEBAQEBAQEBAQEBAQAAAAAAAAAAAAAAAAAAAQEBAQEBAQEBAQEBAQEBAQEBAAAAAAAAAAAAAAAAAAABAQEBAQEBAQEBAQEBAQEBAQEAAAAAAAAAAAAAAAAAAAEBAQEBAQEBAQEBAQEBAQEBAQAAAAAAAAAAAAAAAAAAAQEBAQEBAQEBAQEBAAAAAAAAAAAAAAAAAAAAAAAAAAABAQEBAQEBAQEBAQEAAAAAAAAAAAAAAAAAAAAAAAAAAAEBAQEBAQEBAQEBAQAAAAAAAAAAAAAAAAAAAQEBAQEBAQEBAQEBAQEBAQEBAAAAAAAAAAAAAAAAAAABAQEBAQEBAQEBAQEBAQEBAQEAAAAAAAAAAAAAAAAAAAEBAQEBAQEBAQEBAQEBAQEBAQAAAAAAAAAAAAAAAAAAAQEBAQEBAQEBAQEBAQEBAQEBAAAAAAAAAAAAAAAAAAABAQEBAQEBAQEBAQEBAQEBAQEAAAAAAAAAAAAAAAAAAAEBAQEBAQEBAQEBAQ==" - }, - "palette" : { - "originalArgb8888" : [ -265674 ], - "convertedRgb565" : [ -122 ] } }, "diagnostics" : [ ] @@ -294,14 +294,14 @@ "last_modified" : 1774359772424, "fingerprint" : "eeb7cc665386299403b7be1c272375d5077f3647c587f8033aa8c9275f840562", "metadata" : { + "palette" : { + "originalArgb8888" : [ -265674 ], + "convertedRgb565" : [ -122 ] + }, "tile" : { "width" : 32, "height" : 32, "paletteIndices" : "AQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAAAAAAAAAAABAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEAAAAAAAAAAAEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQAAAAAAAAAAAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAAAAAAAAAAABAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEAAAAAAAAAAAEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQAAAAAAAAAAAQEBAQEBAQEBAQEBAAAAAAAAAAAAAAAAAAAAAAAAAAABAQEBAQEBAQEBAQEAAAAAAAAAAAAAAAAAAAAAAAAAAAEBAQEBAQEBAQEBAQAAAAAAAAAAAAAAAAAAAAAAAAAAAQEBAQEBAQEBAQEBAAAAAAAAAAAAAAAAAAAAAAAAAAABAQEBAQEBAQEBAQEAAAAAAAAAAAAAAAAAAAAAAAAAAAEBAQEBAQEBAQEBAQAAAAAAAAAAAAAAAAAAAAAAAAAAAQEBAQEBAQEBAQEBAAAAAAAAAAAAAAAAAAAAAAAAAAABAQEBAQEBAQEBAQEAAAAAAAAAAAAAAAAAAAAAAAAAAAEBAQEBAQEBAQEBAQAAAAAAAAAAAAAAAAAAAQEBAQEBAQEBAQEBAQEBAQEBAAAAAAAAAAAAAAAAAAABAQEBAQEBAQEBAQEBAQEBAQEAAAAAAAAAAAAAAAAAAAEBAQEBAQEBAQEBAQEBAQEBAQAAAAAAAAAAAAAAAAAAAQEBAQEBAQEBAQEBAAAAAAAAAAAAAAAAAAAAAAAAAAABAQEBAQEBAQEBAQEAAAAAAAAAAAAAAAAAAAAAAAAAAAEBAQEBAQEBAQEBAQAAAAAAAAAAAAAAAAAAAQEBAQEBAQEBAQEBAQEBAQEBAAAAAAAAAAAAAAAAAAABAQEBAQEBAQEBAQEBAQEBAQEAAAAAAAAAAAAAAAAAAAEBAQEBAQEBAQEBAQEBAQEBAQAAAAAAAAAAAAAAAAAAAQEBAQEBAQEBAQEBAQEBAQEBAAAAAAAAAAAAAAAAAAABAQEBAQEBAQEBAQEBAQEBAQEAAAAAAAAAAAAAAAAAAAEBAQEBAQEBAQEBAQ==" - }, - "palette" : { - "originalArgb8888" : [ -265674 ], - "convertedRgb565" : [ -122 ] } }, "diagnostics" : [ ] @@ -312,14 +312,14 @@ "last_modified" : 1774359772425, "fingerprint" : "eeb7cc665386299403b7be1c272375d5077f3647c587f8033aa8c9275f840562", "metadata" : { + "palette" : { + "originalArgb8888" : [ -265674 ], + "convertedRgb565" : [ -122 ] + }, "tile" : { "width" : 32, "height" : 32, "paletteIndices" : "AQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAAAAAAAAAAABAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEAAAAAAAAAAAEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQAAAAAAAAAAAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAAAAAAAAAAABAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEAAAAAAAAAAAEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQAAAAAAAAAAAQEBAQEBAQEBAQEBAAAAAAAAAAAAAAAAAAAAAAAAAAABAQEBAQEBAQEBAQEAAAAAAAAAAAAAAAAAAAAAAAAAAAEBAQEBAQEBAQEBAQAAAAAAAAAAAAAAAAAAAAAAAAAAAQEBAQEBAQEBAQEBAAAAAAAAAAAAAAAAAAAAAAAAAAABAQEBAQEBAQEBAQEAAAAAAAAAAAAAAAAAAAAAAAAAAAEBAQEBAQEBAQEBAQAAAAAAAAAAAAAAAAAAAAAAAAAAAQEBAQEBAQEBAQEBAAAAAAAAAAAAAAAAAAAAAAAAAAABAQEBAQEBAQEBAQEAAAAAAAAAAAAAAAAAAAAAAAAAAAEBAQEBAQEBAQEBAQAAAAAAAAAAAAAAAAAAAQEBAQEBAQEBAQEBAQEBAQEBAAAAAAAAAAAAAAAAAAABAQEBAQEBAQEBAQEBAQEBAQEAAAAAAAAAAAAAAAAAAAEBAQEBAQEBAQEBAQEBAQEBAQAAAAAAAAAAAAAAAAAAAQEBAQEBAQEBAQEBAAAAAAAAAAAAAAAAAAAAAAAAAAABAQEBAQEBAQEBAQEAAAAAAAAAAAAAAAAAAAAAAAAAAAEBAQEBAQEBAQEBAQAAAAAAAAAAAAAAAAAAAQEBAQEBAQEBAQEBAQEBAQEBAAAAAAAAAAAAAAAAAAABAQEBAQEBAQEBAQEBAQEBAQEAAAAAAAAAAAAAAAAAAAEBAQEBAQEBAQEBAQEBAQEBAQAAAAAAAAAAAAAAAAAAAQEBAQEBAQEBAQEBAQEBAQEBAAAAAAAAAAAAAAAAAAABAQEBAQEBAQEBAQEBAQEBAQEAAAAAAAAAAAAAAAAAAAEBAQEBAQEBAQEBAQ==" - }, - "palette" : { - "originalArgb8888" : [ -265674 ], - "convertedRgb565" : [ -122 ] } }, "diagnostics" : [ ] @@ -330,14 +330,14 @@ "last_modified" : 1774359772426, "fingerprint" : "eeb7cc665386299403b7be1c272375d5077f3647c587f8033aa8c9275f840562", "metadata" : { + "palette" : { + "originalArgb8888" : [ -265674 ], + "convertedRgb565" : [ -122 ] + }, "tile" : { "width" : 32, "height" : 32, "paletteIndices" : "AQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAAAAAAAAAAABAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEAAAAAAAAAAAEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQAAAAAAAAAAAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAAAAAAAAAAABAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEAAAAAAAAAAAEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQAAAAAAAAAAAQEBAQEBAQEBAQEBAAAAAAAAAAAAAAAAAAAAAAAAAAABAQEBAQEBAQEBAQEAAAAAAAAAAAAAAAAAAAAAAAAAAAEBAQEBAQEBAQEBAQAAAAAAAAAAAAAAAAAAAAAAAAAAAQEBAQEBAQEBAQEBAAAAAAAAAAAAAAAAAAAAAAAAAAABAQEBAQEBAQEBAQEAAAAAAAAAAAAAAAAAAAAAAAAAAAEBAQEBAQEBAQEBAQAAAAAAAAAAAAAAAAAAAAAAAAAAAQEBAQEBAQEBAQEBAAAAAAAAAAAAAAAAAAAAAAAAAAABAQEBAQEBAQEBAQEAAAAAAAAAAAAAAAAAAAAAAAAAAAEBAQEBAQEBAQEBAQAAAAAAAAAAAAAAAAAAAQEBAQEBAQEBAQEBAQEBAQEBAAAAAAAAAAAAAAAAAAABAQEBAQEBAQEBAQEBAQEBAQEAAAAAAAAAAAAAAAAAAAEBAQEBAQEBAQEBAQEBAQEBAQAAAAAAAAAAAAAAAAAAAQEBAQEBAQEBAQEBAAAAAAAAAAAAAAAAAAAAAAAAAAABAQEBAQEBAQEBAQEAAAAAAAAAAAAAAAAAAAAAAAAAAAEBAQEBAQEBAQEBAQAAAAAAAAAAAAAAAAAAAQEBAQEBAQEBAQEBAQEBAQEBAAAAAAAAAAAAAAAAAAABAQEBAQEBAQEBAQEBAQEBAQEAAAAAAAAAAAAAAAAAAAEBAQEBAQEBAQEBAQEBAQEBAQAAAAAAAAAAAAAAAAAAAQEBAQEBAQEBAQEBAQEBAQEBAAAAAAAAAAAAAAAAAAABAQEBAQEBAQEBAQEBAQEBAQEAAAAAAAAAAAAAAAAAAAEBAQEBAQEBAQEBAQ==" - }, - "palette" : { - "originalArgb8888" : [ -265674 ], - "convertedRgb565" : [ -122 ] } }, "diagnostics" : [ ] @@ -348,14 +348,14 @@ "last_modified" : 1774359772428, "fingerprint" : "eeb7cc665386299403b7be1c272375d5077f3647c587f8033aa8c9275f840562", "metadata" : { + "palette" : { + "originalArgb8888" : [ -265674 ], + "convertedRgb565" : [ -122 ] + }, "tile" : { "width" : 32, "height" : 32, "paletteIndices" : "AQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAAAAAAAAAAABAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEAAAAAAAAAAAEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQAAAAAAAAAAAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAAAAAAAAAAABAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEAAAAAAAAAAAEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQAAAAAAAAAAAQEBAQEBAQEBAQEBAAAAAAAAAAAAAAAAAAAAAAAAAAABAQEBAQEBAQEBAQEAAAAAAAAAAAAAAAAAAAAAAAAAAAEBAQEBAQEBAQEBAQAAAAAAAAAAAAAAAAAAAAAAAAAAAQEBAQEBAQEBAQEBAAAAAAAAAAAAAAAAAAAAAAAAAAABAQEBAQEBAQEBAQEAAAAAAAAAAAAAAAAAAAAAAAAAAAEBAQEBAQEBAQEBAQAAAAAAAAAAAAAAAAAAAAAAAAAAAQEBAQEBAQEBAQEBAAAAAAAAAAAAAAAAAAAAAAAAAAABAQEBAQEBAQEBAQEAAAAAAAAAAAAAAAAAAAAAAAAAAAEBAQEBAQEBAQEBAQAAAAAAAAAAAAAAAAAAAQEBAQEBAQEBAQEBAQEBAQEBAAAAAAAAAAAAAAAAAAABAQEBAQEBAQEBAQEBAQEBAQEAAAAAAAAAAAAAAAAAAAEBAQEBAQEBAQEBAQEBAQEBAQAAAAAAAAAAAAAAAAAAAQEBAQEBAQEBAQEBAAAAAAAAAAAAAAAAAAAAAAAAAAABAQEBAQEBAQEBAQEAAAAAAAAAAAAAAAAAAAAAAAAAAAEBAQEBAQEBAQEBAQAAAAAAAAAAAAAAAAAAAQEBAQEBAQEBAQEBAQEBAQEBAAAAAAAAAAAAAAAAAAABAQEBAQEBAQEBAQEBAQEBAQEAAAAAAAAAAAAAAAAAAAEBAQEBAQEBAQEBAQEBAQEBAQAAAAAAAAAAAAAAAAAAAQEBAQEBAQEBAQEBAQEBAQEBAAAAAAAAAAAAAAAAAAABAQEBAQEBAQEBAQEBAQEBAQEAAAAAAAAAAAAAAAAAAAEBAQEBAQEBAQEBAQ==" - }, - "palette" : { - "originalArgb8888" : [ -265674 ], - "convertedRgb565" : [ -122 ] } }, "diagnostics" : [ ] @@ -366,14 +366,14 @@ "last_modified" : 1774359772429, "fingerprint" : "eeb7cc665386299403b7be1c272375d5077f3647c587f8033aa8c9275f840562", "metadata" : { + "palette" : { + "originalArgb8888" : [ -265674 ], + "convertedRgb565" : [ -122 ] + }, "tile" : { "width" : 32, "height" : 32, "paletteIndices" : "AQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAAAAAAAAAAABAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEAAAAAAAAAAAEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQAAAAAAAAAAAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAAAAAAAAAAABAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEAAAAAAAAAAAEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQAAAAAAAAAAAQEBAQEBAQEBAQEBAAAAAAAAAAAAAAAAAAAAAAAAAAABAQEBAQEBAQEBAQEAAAAAAAAAAAAAAAAAAAAAAAAAAAEBAQEBAQEBAQEBAQAAAAAAAAAAAAAAAAAAAAAAAAAAAQEBAQEBAQEBAQEBAAAAAAAAAAAAAAAAAAAAAAAAAAABAQEBAQEBAQEBAQEAAAAAAAAAAAAAAAAAAAAAAAAAAAEBAQEBAQEBAQEBAQAAAAAAAAAAAAAAAAAAAAAAAAAAAQEBAQEBAQEBAQEBAAAAAAAAAAAAAAAAAAAAAAAAAAABAQEBAQEBAQEBAQEAAAAAAAAAAAAAAAAAAAAAAAAAAAEBAQEBAQEBAQEBAQAAAAAAAAAAAAAAAAAAAQEBAQEBAQEBAQEBAQEBAQEBAAAAAAAAAAAAAAAAAAABAQEBAQEBAQEBAQEBAQEBAQEAAAAAAAAAAAAAAAAAAAEBAQEBAQEBAQEBAQEBAQEBAQAAAAAAAAAAAAAAAAAAAQEBAQEBAQEBAQEBAAAAAAAAAAAAAAAAAAAAAAAAAAABAQEBAQEBAQEBAQEAAAAAAAAAAAAAAAAAAAAAAAAAAAEBAQEBAQEBAQEBAQAAAAAAAAAAAAAAAAAAAQEBAQEBAQEBAQEBAQEBAQEBAAAAAAAAAAAAAAAAAAABAQEBAQEBAQEBAQEBAQEBAQEAAAAAAAAAAAAAAAAAAAEBAQEBAQEBAQEBAQEBAQEBAQAAAAAAAAAAAAAAAAAAAQEBAQEBAQEBAQEBAQEBAQEBAAAAAAAAAAAAAAAAAAABAQEBAQEBAQEBAQEBAQEBAQEAAAAAAAAAAAAAAAAAAAEBAQEBAQEBAQEBAQ==" - }, - "palette" : { - "originalArgb8888" : [ -265674 ], - "convertedRgb565" : [ -122 ] } }, "diagnostics" : [ ] @@ -384,14 +384,14 @@ "last_modified" : 1774359772430, "fingerprint" : "eeb7cc665386299403b7be1c272375d5077f3647c587f8033aa8c9275f840562", "metadata" : { + "palette" : { + "originalArgb8888" : [ -265674 ], + "convertedRgb565" : [ -122 ] + }, "tile" : { "width" : 32, "height" : 32, "paletteIndices" : "AQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAAAAAAAAAAABAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEAAAAAAAAAAAEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQAAAAAAAAAAAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAAAAAAAAAAABAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEAAAAAAAAAAAEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQAAAAAAAAAAAQEBAQEBAQEBAQEBAAAAAAAAAAAAAAAAAAAAAAAAAAABAQEBAQEBAQEBAQEAAAAAAAAAAAAAAAAAAAAAAAAAAAEBAQEBAQEBAQEBAQAAAAAAAAAAAAAAAAAAAAAAAAAAAQEBAQEBAQEBAQEBAAAAAAAAAAAAAAAAAAAAAAAAAAABAQEBAQEBAQEBAQEAAAAAAAAAAAAAAAAAAAAAAAAAAAEBAQEBAQEBAQEBAQAAAAAAAAAAAAAAAAAAAAAAAAAAAQEBAQEBAQEBAQEBAAAAAAAAAAAAAAAAAAAAAAAAAAABAQEBAQEBAQEBAQEAAAAAAAAAAAAAAAAAAAAAAAAAAAEBAQEBAQEBAQEBAQAAAAAAAAAAAAAAAAAAAQEBAQEBAQEBAQEBAQEBAQEBAAAAAAAAAAAAAAAAAAABAQEBAQEBAQEBAQEBAQEBAQEAAAAAAAAAAAAAAAAAAAEBAQEBAQEBAQEBAQEBAQEBAQAAAAAAAAAAAAAAAAAAAQEBAQEBAQEBAQEBAAAAAAAAAAAAAAAAAAAAAAAAAAABAQEBAQEBAQEBAQEAAAAAAAAAAAAAAAAAAAAAAAAAAAEBAQEBAQEBAQEBAQAAAAAAAAAAAAAAAAAAAQEBAQEBAQEBAQEBAQEBAQEBAAAAAAAAAAAAAAAAAAABAQEBAQEBAQEBAQEBAQEBAQEAAAAAAAAAAAAAAAAAAAEBAQEBAQEBAQEBAQEBAQEBAQAAAAAAAAAAAAAAAAAAAQEBAQEBAQEBAQEBAQEBAQEBAAAAAAAAAAAAAAAAAAABAQEBAQEBAQEBAQEBAQEBAQEAAAAAAAAAAAAAAAAAAAEBAQEBAQEBAQEBAQ==" - }, - "palette" : { - "originalArgb8888" : [ -265674 ], - "convertedRgb565" : [ -122 ] } }, "diagnostics" : [ ] @@ -402,14 +402,14 @@ "last_modified" : 1774359772431, "fingerprint" : "eeb7cc665386299403b7be1c272375d5077f3647c587f8033aa8c9275f840562", "metadata" : { + "palette" : { + "originalArgb8888" : [ -265674 ], + "convertedRgb565" : [ -122 ] + }, "tile" : { "width" : 32, "height" : 32, "paletteIndices" : "AQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAAAAAAAAAAABAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEAAAAAAAAAAAEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQAAAAAAAAAAAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAAAAAAAAAAABAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEAAAAAAAAAAAEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQAAAAAAAAAAAQEBAQEBAQEBAQEBAAAAAAAAAAAAAAAAAAAAAAAAAAABAQEBAQEBAQEBAQEAAAAAAAAAAAAAAAAAAAAAAAAAAAEBAQEBAQEBAQEBAQAAAAAAAAAAAAAAAAAAAAAAAAAAAQEBAQEBAQEBAQEBAAAAAAAAAAAAAAAAAAAAAAAAAAABAQEBAQEBAQEBAQEAAAAAAAAAAAAAAAAAAAAAAAAAAAEBAQEBAQEBAQEBAQAAAAAAAAAAAAAAAAAAAAAAAAAAAQEBAQEBAQEBAQEBAAAAAAAAAAAAAAAAAAAAAAAAAAABAQEBAQEBAQEBAQEAAAAAAAAAAAAAAAAAAAAAAAAAAAEBAQEBAQEBAQEBAQAAAAAAAAAAAAAAAAAAAQEBAQEBAQEBAQEBAQEBAQEBAAAAAAAAAAAAAAAAAAABAQEBAQEBAQEBAQEBAQEBAQEAAAAAAAAAAAAAAAAAAAEBAQEBAQEBAQEBAQEBAQEBAQAAAAAAAAAAAAAAAAAAAQEBAQEBAQEBAQEBAAAAAAAAAAAAAAAAAAAAAAAAAAABAQEBAQEBAQEBAQEAAAAAAAAAAAAAAAAAAAAAAAAAAAEBAQEBAQEBAQEBAQAAAAAAAAAAAAAAAAAAAQEBAQEBAQEBAQEBAQEBAQEBAAAAAAAAAAAAAAAAAAABAQEBAQEBAQEBAQEBAQEBAQEAAAAAAAAAAAAAAAAAAAEBAQEBAQEBAQEBAQEBAQEBAQAAAAAAAAAAAAAAAAAAAQEBAQEBAQEBAQEBAQEBAQEBAAAAAAAAAAAAAAAAAAABAQEBAQEBAQEBAQEBAQEBAQEAAAAAAAAAAAAAAAAAAAEBAQEBAQEBAQEBAQ==" - }, - "palette" : { - "originalArgb8888" : [ -265674 ], - "convertedRgb565" : [ -122 ] } }, "diagnostics" : [ ] @@ -420,14 +420,14 @@ "last_modified" : 1774359772432, "fingerprint" : "eeb7cc665386299403b7be1c272375d5077f3647c587f8033aa8c9275f840562", "metadata" : { + "palette" : { + "originalArgb8888" : [ -265674 ], + "convertedRgb565" : [ -122 ] + }, "tile" : { "width" : 32, "height" : 32, "paletteIndices" : "AQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAAAAAAAAAAABAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEAAAAAAAAAAAEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQAAAAAAAAAAAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAAAAAAAAAAABAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEAAAAAAAAAAAEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQAAAAAAAAAAAQEBAQEBAQEBAQEBAAAAAAAAAAAAAAAAAAAAAAAAAAABAQEBAQEBAQEBAQEAAAAAAAAAAAAAAAAAAAAAAAAAAAEBAQEBAQEBAQEBAQAAAAAAAAAAAAAAAAAAAAAAAAAAAQEBAQEBAQEBAQEBAAAAAAAAAAAAAAAAAAAAAAAAAAABAQEBAQEBAQEBAQEAAAAAAAAAAAAAAAAAAAAAAAAAAAEBAQEBAQEBAQEBAQAAAAAAAAAAAAAAAAAAAAAAAAAAAQEBAQEBAQEBAQEBAAAAAAAAAAAAAAAAAAAAAAAAAAABAQEBAQEBAQEBAQEAAAAAAAAAAAAAAAAAAAAAAAAAAAEBAQEBAQEBAQEBAQAAAAAAAAAAAAAAAAAAAQEBAQEBAQEBAQEBAQEBAQEBAAAAAAAAAAAAAAAAAAABAQEBAQEBAQEBAQEBAQEBAQEAAAAAAAAAAAAAAAAAAAEBAQEBAQEBAQEBAQEBAQEBAQAAAAAAAAAAAAAAAAAAAQEBAQEBAQEBAQEBAAAAAAAAAAAAAAAAAAAAAAAAAAABAQEBAQEBAQEBAQEAAAAAAAAAAAAAAAAAAAAAAAAAAAEBAQEBAQEBAQEBAQAAAAAAAAAAAAAAAAAAAQEBAQEBAQEBAQEBAQEBAQEBAAAAAAAAAAAAAAAAAAABAQEBAQEBAQEBAQEBAQEBAQEAAAAAAAAAAAAAAAAAAAEBAQEBAQEBAQEBAQEBAQEBAQAAAAAAAAAAAAAAAAAAAQEBAQEBAQEBAQEBAQEBAQEBAAAAAAAAAAAAAAAAAAABAQEBAQEBAQEBAQEBAQEBAQEAAAAAAAAAAAAAAAAAAAEBAQEBAQEBAQEBAQ==" - }, - "palette" : { - "originalArgb8888" : [ -265674 ], - "convertedRgb565" : [ -122 ] } }, "diagnostics" : [ ] @@ -438,14 +438,14 @@ "last_modified" : 1774359772433, "fingerprint" : "eeb7cc665386299403b7be1c272375d5077f3647c587f8033aa8c9275f840562", "metadata" : { + "palette" : { + "originalArgb8888" : [ -265674 ], + "convertedRgb565" : [ -122 ] + }, "tile" : { "width" : 32, "height" : 32, "paletteIndices" : "AQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAAAAAAAAAAABAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEAAAAAAAAAAAEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQAAAAAAAAAAAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAAAAAAAAAAABAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEAAAAAAAAAAAEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQAAAAAAAAAAAQEBAQEBAQEBAQEBAAAAAAAAAAAAAAAAAAAAAAAAAAABAQEBAQEBAQEBAQEAAAAAAAAAAAAAAAAAAAAAAAAAAAEBAQEBAQEBAQEBAQAAAAAAAAAAAAAAAAAAAAAAAAAAAQEBAQEBAQEBAQEBAAAAAAAAAAAAAAAAAAAAAAAAAAABAQEBAQEBAQEBAQEAAAAAAAAAAAAAAAAAAAAAAAAAAAEBAQEBAQEBAQEBAQAAAAAAAAAAAAAAAAAAAAAAAAAAAQEBAQEBAQEBAQEBAAAAAAAAAAAAAAAAAAAAAAAAAAABAQEBAQEBAQEBAQEAAAAAAAAAAAAAAAAAAAAAAAAAAAEBAQEBAQEBAQEBAQAAAAAAAAAAAAAAAAAAAQEBAQEBAQEBAQEBAQEBAQEBAAAAAAAAAAAAAAAAAAABAQEBAQEBAQEBAQEBAQEBAQEAAAAAAAAAAAAAAAAAAAEBAQEBAQEBAQEBAQEBAQEBAQAAAAAAAAAAAAAAAAAAAQEBAQEBAQEBAQEBAAAAAAAAAAAAAAAAAAAAAAAAAAABAQEBAQEBAQEBAQEAAAAAAAAAAAAAAAAAAAAAAAAAAAEBAQEBAQEBAQEBAQAAAAAAAAAAAAAAAAAAAQEBAQEBAQEBAQEBAQEBAQEBAAAAAAAAAAAAAAAAAAABAQEBAQEBAQEBAQEBAQEBAQEAAAAAAAAAAAAAAAAAAAEBAQEBAQEBAQEBAQEBAQEBAQAAAAAAAAAAAAAAAAAAAQEBAQEBAQEBAQEBAQEBAQEBAAAAAAAAAAAAAAAAAAABAQEBAQEBAQEBAQEBAQEBAQEAAAAAAAAAAAAAAAAAAAEBAQEBAQEBAQEBAQ==" - }, - "palette" : { - "originalArgb8888" : [ -265674 ], - "convertedRgb565" : [ -122 ] } }, "diagnostics" : [ ] @@ -456,14 +456,14 @@ "last_modified" : 1774359772435, "fingerprint" : "eeb7cc665386299403b7be1c272375d5077f3647c587f8033aa8c9275f840562", "metadata" : { + "palette" : { + "originalArgb8888" : [ -265674 ], + "convertedRgb565" : [ -122 ] + }, "tile" : { "width" : 32, "height" : 32, "paletteIndices" : "AQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAAAAAAAAAAABAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEAAAAAAAAAAAEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQAAAAAAAAAAAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAAAAAAAAAAABAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEAAAAAAAAAAAEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQAAAAAAAAAAAQEBAQEBAQEBAQEBAAAAAAAAAAAAAAAAAAAAAAAAAAABAQEBAQEBAQEBAQEAAAAAAAAAAAAAAAAAAAAAAAAAAAEBAQEBAQEBAQEBAQAAAAAAAAAAAAAAAAAAAAAAAAAAAQEBAQEBAQEBAQEBAAAAAAAAAAAAAAAAAAAAAAAAAAABAQEBAQEBAQEBAQEAAAAAAAAAAAAAAAAAAAAAAAAAAAEBAQEBAQEBAQEBAQAAAAAAAAAAAAAAAAAAAAAAAAAAAQEBAQEBAQEBAQEBAAAAAAAAAAAAAAAAAAAAAAAAAAABAQEBAQEBAQEBAQEAAAAAAAAAAAAAAAAAAAAAAAAAAAEBAQEBAQEBAQEBAQAAAAAAAAAAAAAAAAAAAQEBAQEBAQEBAQEBAQEBAQEBAAAAAAAAAAAAAAAAAAABAQEBAQEBAQEBAQEBAQEBAQEAAAAAAAAAAAAAAAAAAAEBAQEBAQEBAQEBAQEBAQEBAQAAAAAAAAAAAAAAAAAAAQEBAQEBAQEBAQEBAAAAAAAAAAAAAAAAAAAAAAAAAAABAQEBAQEBAQEBAQEAAAAAAAAAAAAAAAAAAAAAAAAAAAEBAQEBAQEBAQEBAQAAAAAAAAAAAAAAAAAAAQEBAQEBAQEBAQEBAQEBAQEBAAAAAAAAAAAAAAAAAAABAQEBAQEBAQEBAQEBAQEBAQEAAAAAAAAAAAAAAAAAAAEBAQEBAQEBAQEBAQEBAQEBAQAAAAAAAAAAAAAAAAAAAQEBAQEBAQEBAQEBAQEBAQEBAAAAAAAAAAAAAAAAAAABAQEBAQEBAQEBAQEBAQEBAQEAAAAAAAAAAAAAAAAAAAEBAQEBAQEBAQEBAQ==" - }, - "palette" : { - "originalArgb8888" : [ -265674 ], - "convertedRgb565" : [ -122 ] } }, "diagnostics" : [ ] @@ -474,14 +474,14 @@ "last_modified" : 1774359772436, "fingerprint" : "eeb7cc665386299403b7be1c272375d5077f3647c587f8033aa8c9275f840562", "metadata" : { + "palette" : { + "originalArgb8888" : [ -265674 ], + "convertedRgb565" : [ -122 ] + }, "tile" : { "width" : 32, "height" : 32, "paletteIndices" : "AQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAAAAAAAAAAABAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEAAAAAAAAAAAEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQAAAAAAAAAAAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAAAAAAAAAAABAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEAAAAAAAAAAAEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQAAAAAAAAAAAQEBAQEBAQEBAQEBAAAAAAAAAAAAAAAAAAAAAAAAAAABAQEBAQEBAQEBAQEAAAAAAAAAAAAAAAAAAAAAAAAAAAEBAQEBAQEBAQEBAQAAAAAAAAAAAAAAAAAAAAAAAAAAAQEBAQEBAQEBAQEBAAAAAAAAAAAAAAAAAAAAAAAAAAABAQEBAQEBAQEBAQEAAAAAAAAAAAAAAAAAAAAAAAAAAAEBAQEBAQEBAQEBAQAAAAAAAAAAAAAAAAAAAAAAAAAAAQEBAQEBAQEBAQEBAAAAAAAAAAAAAAAAAAAAAAAAAAABAQEBAQEBAQEBAQEAAAAAAAAAAAAAAAAAAAAAAAAAAAEBAQEBAQEBAQEBAQAAAAAAAAAAAAAAAAAAAQEBAQEBAQEBAQEBAQEBAQEBAAAAAAAAAAAAAAAAAAABAQEBAQEBAQEBAQEBAQEBAQEAAAAAAAAAAAAAAAAAAAEBAQEBAQEBAQEBAQEBAQEBAQAAAAAAAAAAAAAAAAAAAQEBAQEBAQEBAQEBAAAAAAAAAAAAAAAAAAAAAAAAAAABAQEBAQEBAQEBAQEAAAAAAAAAAAAAAAAAAAAAAAAAAAEBAQEBAQEBAQEBAQAAAAAAAAAAAAAAAAAAAQEBAQEBAQEBAQEBAQEBAQEBAAAAAAAAAAAAAAAAAAABAQEBAQEBAQEBAQEBAQEBAQEAAAAAAAAAAAAAAAAAAAEBAQEBAQEBAQEBAQEBAQEBAQAAAAAAAAAAAAAAAAAAAQEBAQEBAQEBAQEBAQEBAQEBAAAAAAAAAAAAAAAAAAABAQEBAQEBAQEBAQEBAQEBAQEAAAAAAAAAAAAAAAAAAAEBAQEBAQEBAQEBAQ==" - }, - "palette" : { - "originalArgb8888" : [ -265674 ], - "convertedRgb565" : [ -122 ] } }, "diagnostics" : [ ] @@ -492,14 +492,14 @@ "last_modified" : 1774359772437, "fingerprint" : "eeb7cc665386299403b7be1c272375d5077f3647c587f8033aa8c9275f840562", "metadata" : { + "palette" : { + "originalArgb8888" : [ -265674 ], + "convertedRgb565" : [ -122 ] + }, "tile" : { "width" : 32, "height" : 32, "paletteIndices" : "AQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAAAAAAAAAAABAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEAAAAAAAAAAAEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQAAAAAAAAAAAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAAAAAAAAAAABAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEAAAAAAAAAAAEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQAAAAAAAAAAAQEBAQEBAQEBAQEBAAAAAAAAAAAAAAAAAAAAAAAAAAABAQEBAQEBAQEBAQEAAAAAAAAAAAAAAAAAAAAAAAAAAAEBAQEBAQEBAQEBAQAAAAAAAAAAAAAAAAAAAAAAAAAAAQEBAQEBAQEBAQEBAAAAAAAAAAAAAAAAAAAAAAAAAAABAQEBAQEBAQEBAQEAAAAAAAAAAAAAAAAAAAAAAAAAAAEBAQEBAQEBAQEBAQAAAAAAAAAAAAAAAAAAAAAAAAAAAQEBAQEBAQEBAQEBAAAAAAAAAAAAAAAAAAAAAAAAAAABAQEBAQEBAQEBAQEAAAAAAAAAAAAAAAAAAAAAAAAAAAEBAQEBAQEBAQEBAQAAAAAAAAAAAAAAAAAAAQEBAQEBAQEBAQEBAQEBAQEBAAAAAAAAAAAAAAAAAAABAQEBAQEBAQEBAQEBAQEBAQEAAAAAAAAAAAAAAAAAAAEBAQEBAQEBAQEBAQEBAQEBAQAAAAAAAAAAAAAAAAAAAQEBAQEBAQEBAQEBAAAAAAAAAAAAAAAAAAAAAAAAAAABAQEBAQEBAQEBAQEAAAAAAAAAAAAAAAAAAAAAAAAAAAEBAQEBAQEBAQEBAQAAAAAAAAAAAAAAAAAAAQEBAQEBAQEBAQEBAQEBAQEBAAAAAAAAAAAAAAAAAAABAQEBAQEBAQEBAQEBAQEBAQEAAAAAAAAAAAAAAAAAAAEBAQEBAQEBAQEBAQEBAQEBAQAAAAAAAAAAAAAAAAAAAQEBAQEBAQEBAQEBAQEBAQEBAAAAAAAAAAAAAAAAAAABAQEBAQEBAQEBAQEBAQEBAQEAAAAAAAAAAAAAAAAAAAEBAQEBAQEBAQEBAQ==" - }, - "palette" : { - "originalArgb8888" : [ -265674 ], - "convertedRgb565" : [ -122 ] } }, "diagnostics" : [ ] @@ -510,14 +510,14 @@ "last_modified" : 1774359772438, "fingerprint" : "eeb7cc665386299403b7be1c272375d5077f3647c587f8033aa8c9275f840562", "metadata" : { + "palette" : { + "originalArgb8888" : [ -265674 ], + "convertedRgb565" : [ -122 ] + }, "tile" : { "width" : 32, "height" : 32, "paletteIndices" : "AQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAAAAAAAAAAABAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEAAAAAAAAAAAEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQAAAAAAAAAAAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAAAAAAAAAAABAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEAAAAAAAAAAAEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQAAAAAAAAAAAQEBAQEBAQEBAQEBAAAAAAAAAAAAAAAAAAAAAAAAAAABAQEBAQEBAQEBAQEAAAAAAAAAAAAAAAAAAAAAAAAAAAEBAQEBAQEBAQEBAQAAAAAAAAAAAAAAAAAAAAAAAAAAAQEBAQEBAQEBAQEBAAAAAAAAAAAAAAAAAAAAAAAAAAABAQEBAQEBAQEBAQEAAAAAAAAAAAAAAAAAAAAAAAAAAAEBAQEBAQEBAQEBAQAAAAAAAAAAAAAAAAAAAAAAAAAAAQEBAQEBAQEBAQEBAAAAAAAAAAAAAAAAAAAAAAAAAAABAQEBAQEBAQEBAQEAAAAAAAAAAAAAAAAAAAAAAAAAAAEBAQEBAQEBAQEBAQAAAAAAAAAAAAAAAAAAAQEBAQEBAQEBAQEBAQEBAQEBAAAAAAAAAAAAAAAAAAABAQEBAQEBAQEBAQEBAQEBAQEAAAAAAAAAAAAAAAAAAAEBAQEBAQEBAQEBAQEBAQEBAQAAAAAAAAAAAAAAAAAAAQEBAQEBAQEBAQEBAAAAAAAAAAAAAAAAAAAAAAAAAAABAQEBAQEBAQEBAQEAAAAAAAAAAAAAAAAAAAAAAAAAAAEBAQEBAQEBAQEBAQAAAAAAAAAAAAAAAAAAAQEBAQEBAQEBAQEBAQEBAQEBAAAAAAAAAAAAAAAAAAABAQEBAQEBAQEBAQEBAQEBAQEAAAAAAAAAAAAAAAAAAAEBAQEBAQEBAQEBAQEBAQEBAQAAAAAAAAAAAAAAAAAAAQEBAQEBAQEBAQEBAQEBAQEBAAAAAAAAAAAAAAAAAAABAQEBAQEBAQEBAQEBAQEBAQEAAAAAAAAAAAAAAAAAAAEBAQEBAQEBAQEBAQ==" - }, - "palette" : { - "originalArgb8888" : [ -265674 ], - "convertedRgb565" : [ -122 ] } }, "diagnostics" : [ ] @@ -528,14 +528,14 @@ "last_modified" : 1774359772439, "fingerprint" : "eeb7cc665386299403b7be1c272375d5077f3647c587f8033aa8c9275f840562", "metadata" : { + "palette" : { + "originalArgb8888" : [ -265674 ], + "convertedRgb565" : [ -122 ] + }, "tile" : { "width" : 32, "height" : 32, "paletteIndices" : "AQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAAAAAAAAAAABAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEAAAAAAAAAAAEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQAAAAAAAAAAAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAAAAAAAAAAABAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEAAAAAAAAAAAEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQAAAAAAAAAAAQEBAQEBAQEBAQEBAAAAAAAAAAAAAAAAAAAAAAAAAAABAQEBAQEBAQEBAQEAAAAAAAAAAAAAAAAAAAAAAAAAAAEBAQEBAQEBAQEBAQAAAAAAAAAAAAAAAAAAAAAAAAAAAQEBAQEBAQEBAQEBAAAAAAAAAAAAAAAAAAAAAAAAAAABAQEBAQEBAQEBAQEAAAAAAAAAAAAAAAAAAAAAAAAAAAEBAQEBAQEBAQEBAQAAAAAAAAAAAAAAAAAAAAAAAAAAAQEBAQEBAQEBAQEBAAAAAAAAAAAAAAAAAAAAAAAAAAABAQEBAQEBAQEBAQEAAAAAAAAAAAAAAAAAAAAAAAAAAAEBAQEBAQEBAQEBAQAAAAAAAAAAAAAAAAAAAQEBAQEBAQEBAQEBAQEBAQEBAAAAAAAAAAAAAAAAAAABAQEBAQEBAQEBAQEBAQEBAQEAAAAAAAAAAAAAAAAAAAEBAQEBAQEBAQEBAQEBAQEBAQAAAAAAAAAAAAAAAAAAAQEBAQEBAQEBAQEBAAAAAAAAAAAAAAAAAAAAAAAAAAABAQEBAQEBAQEBAQEAAAAAAAAAAAAAAAAAAAAAAAAAAAEBAQEBAQEBAQEBAQAAAAAAAAAAAAAAAAAAAQEBAQEBAQEBAQEBAQEBAQEBAAAAAAAAAAAAAAAAAAABAQEBAQEBAQEBAQEBAQEBAQEAAAAAAAAAAAAAAAAAAAEBAQEBAQEBAQEBAQEBAQEBAQAAAAAAAAAAAAAAAAAAAQEBAQEBAQEBAQEBAQEBAQEBAAAAAAAAAAAAAAAAAAABAQEBAQEBAQEBAQEBAQEBAQEAAAAAAAAAAAAAAAAAAAEBAQEBAQEBAQEBAQ==" - }, - "palette" : { - "originalArgb8888" : [ -265674 ], - "convertedRgb565" : [ -122 ] } }, "diagnostics" : [ ] @@ -546,14 +546,14 @@ "last_modified" : 1774359772441, "fingerprint" : "eeb7cc665386299403b7be1c272375d5077f3647c587f8033aa8c9275f840562", "metadata" : { + "palette" : { + "originalArgb8888" : [ -265674 ], + "convertedRgb565" : [ -122 ] + }, "tile" : { "width" : 32, "height" : 32, "paletteIndices" : "AQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAAAAAAAAAAABAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEAAAAAAAAAAAEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQAAAAAAAAAAAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAAAAAAAAAAABAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEAAAAAAAAAAAEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQAAAAAAAAAAAQEBAQEBAQEBAQEBAAAAAAAAAAAAAAAAAAAAAAAAAAABAQEBAQEBAQEBAQEAAAAAAAAAAAAAAAAAAAAAAAAAAAEBAQEBAQEBAQEBAQAAAAAAAAAAAAAAAAAAAAAAAAAAAQEBAQEBAQEBAQEBAAAAAAAAAAAAAAAAAAAAAAAAAAABAQEBAQEBAQEBAQEAAAAAAAAAAAAAAAAAAAAAAAAAAAEBAQEBAQEBAQEBAQAAAAAAAAAAAAAAAAAAAAAAAAAAAQEBAQEBAQEBAQEBAAAAAAAAAAAAAAAAAAAAAAAAAAABAQEBAQEBAQEBAQEAAAAAAAAAAAAAAAAAAAAAAAAAAAEBAQEBAQEBAQEBAQAAAAAAAAAAAAAAAAAAAQEBAQEBAQEBAQEBAQEBAQEBAAAAAAAAAAAAAAAAAAABAQEBAQEBAQEBAQEBAQEBAQEAAAAAAAAAAAAAAAAAAAEBAQEBAQEBAQEBAQEBAQEBAQAAAAAAAAAAAAAAAAAAAQEBAQEBAQEBAQEBAAAAAAAAAAAAAAAAAAAAAAAAAAABAQEBAQEBAQEBAQEAAAAAAAAAAAAAAAAAAAAAAAAAAAEBAQEBAQEBAQEBAQAAAAAAAAAAAAAAAAAAAQEBAQEBAQEBAQEBAQEBAQEBAAAAAAAAAAAAAAAAAAABAQEBAQEBAQEBAQEBAQEBAQEAAAAAAAAAAAAAAAAAAAEBAQEBAQEBAQEBAQEBAQEBAQAAAAAAAAAAAAAAAAAAAQEBAQEBAQEBAQEBAQEBAQEBAAAAAAAAAAAAAAAAAAABAQEBAQEBAQEBAQEBAQEBAQEAAAAAAAAAAAAAAAAAAAEBAQEBAQEBAQEBAQ==" - }, - "palette" : { - "originalArgb8888" : [ -265674 ], - "convertedRgb565" : [ -122 ] } }, "diagnostics" : [ ] @@ -564,14 +564,14 @@ "last_modified" : 1774359772442, "fingerprint" : "eeb7cc665386299403b7be1c272375d5077f3647c587f8033aa8c9275f840562", "metadata" : { + "palette" : { + "originalArgb8888" : [ -265674 ], + "convertedRgb565" : [ -122 ] + }, "tile" : { "width" : 32, "height" : 32, "paletteIndices" : "AQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAAAAAAAAAAABAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEAAAAAAAAAAAEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQAAAAAAAAAAAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAAAAAAAAAAABAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEAAAAAAAAAAAEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQAAAAAAAAAAAQEBAQEBAQEBAQEBAAAAAAAAAAAAAAAAAAAAAAAAAAABAQEBAQEBAQEBAQEAAAAAAAAAAAAAAAAAAAAAAAAAAAEBAQEBAQEBAQEBAQAAAAAAAAAAAAAAAAAAAAAAAAAAAQEBAQEBAQEBAQEBAAAAAAAAAAAAAAAAAAAAAAAAAAABAQEBAQEBAQEBAQEAAAAAAAAAAAAAAAAAAAAAAAAAAAEBAQEBAQEBAQEBAQAAAAAAAAAAAAAAAAAAAAAAAAAAAQEBAQEBAQEBAQEBAAAAAAAAAAAAAAAAAAAAAAAAAAABAQEBAQEBAQEBAQEAAAAAAAAAAAAAAAAAAAAAAAAAAAEBAQEBAQEBAQEBAQAAAAAAAAAAAAAAAAAAAQEBAQEBAQEBAQEBAQEBAQEBAAAAAAAAAAAAAAAAAAABAQEBAQEBAQEBAQEBAQEBAQEAAAAAAAAAAAAAAAAAAAEBAQEBAQEBAQEBAQEBAQEBAQAAAAAAAAAAAAAAAAAAAQEBAQEBAQEBAQEBAAAAAAAAAAAAAAAAAAAAAAAAAAABAQEBAQEBAQEBAQEAAAAAAAAAAAAAAAAAAAAAAAAAAAEBAQEBAQEBAQEBAQAAAAAAAAAAAAAAAAAAAQEBAQEBAQEBAQEBAQEBAQEBAAAAAAAAAAAAAAAAAAABAQEBAQEBAQEBAQEBAQEBAQEAAAAAAAAAAAAAAAAAAAEBAQEBAQEBAQEBAQEBAQEBAQAAAAAAAAAAAAAAAAAAAQEBAQEBAQEBAQEBAQEBAQEBAAAAAAAAAAAAAAAAAAABAQEBAQEBAQEBAQEBAQEBAQEAAAAAAAAAAAAAAAAAAAEBAQEBAQEBAQEBAQ==" - }, - "palette" : { - "originalArgb8888" : [ -265674 ], - "convertedRgb565" : [ -122 ] } }, "diagnostics" : [ ] @@ -582,14 +582,14 @@ "last_modified" : 1774359772443, "fingerprint" : "eeb7cc665386299403b7be1c272375d5077f3647c587f8033aa8c9275f840562", "metadata" : { + "palette" : { + "originalArgb8888" : [ -265674 ], + "convertedRgb565" : [ -122 ] + }, "tile" : { "width" : 32, "height" : 32, "paletteIndices" : "AQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAAAAAAAAAAABAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEAAAAAAAAAAAEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQAAAAAAAAAAAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAAAAAAAAAAABAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEAAAAAAAAAAAEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQAAAAAAAAAAAQEBAQEBAQEBAQEBAAAAAAAAAAAAAAAAAAAAAAAAAAABAQEBAQEBAQEBAQEAAAAAAAAAAAAAAAAAAAAAAAAAAAEBAQEBAQEBAQEBAQAAAAAAAAAAAAAAAAAAAAAAAAAAAQEBAQEBAQEBAQEBAAAAAAAAAAAAAAAAAAAAAAAAAAABAQEBAQEBAQEBAQEAAAAAAAAAAAAAAAAAAAAAAAAAAAEBAQEBAQEBAQEBAQAAAAAAAAAAAAAAAAAAAAAAAAAAAQEBAQEBAQEBAQEBAAAAAAAAAAAAAAAAAAAAAAAAAAABAQEBAQEBAQEBAQEAAAAAAAAAAAAAAAAAAAAAAAAAAAEBAQEBAQEBAQEBAQAAAAAAAAAAAAAAAAAAAQEBAQEBAQEBAQEBAQEBAQEBAAAAAAAAAAAAAAAAAAABAQEBAQEBAQEBAQEBAQEBAQEAAAAAAAAAAAAAAAAAAAEBAQEBAQEBAQEBAQEBAQEBAQAAAAAAAAAAAAAAAAAAAQEBAQEBAQEBAQEBAAAAAAAAAAAAAAAAAAAAAAAAAAABAQEBAQEBAQEBAQEAAAAAAAAAAAAAAAAAAAAAAAAAAAEBAQEBAQEBAQEBAQAAAAAAAAAAAAAAAAAAAQEBAQEBAQEBAQEBAQEBAQEBAAAAAAAAAAAAAAAAAAABAQEBAQEBAQEBAQEBAQEBAQEAAAAAAAAAAAAAAAAAAAEBAQEBAQEBAQEBAQEBAQEBAQAAAAAAAAAAAAAAAAAAAQEBAQEBAQEBAQEBAQEBAQEBAAAAAAAAAAAAAAAAAAABAQEBAQEBAQEBAQEBAQEBAQEAAAAAAAAAAAAAAAAAAAEBAQEBAQEBAQEBAQ==" - }, - "palette" : { - "originalArgb8888" : [ -265674 ], - "convertedRgb565" : [ -122 ] } }, "diagnostics" : [ ] @@ -600,14 +600,14 @@ "last_modified" : 1774359772444, "fingerprint" : "eeb7cc665386299403b7be1c272375d5077f3647c587f8033aa8c9275f840562", "metadata" : { + "palette" : { + "originalArgb8888" : [ -265674 ], + "convertedRgb565" : [ -122 ] + }, "tile" : { "width" : 32, "height" : 32, "paletteIndices" : "AQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAAAAAAAAAAABAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEAAAAAAAAAAAEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQAAAAAAAAAAAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAAAAAAAAAAABAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEAAAAAAAAAAAEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQAAAAAAAAAAAQEBAQEBAQEBAQEBAAAAAAAAAAAAAAAAAAAAAAAAAAABAQEBAQEBAQEBAQEAAAAAAAAAAAAAAAAAAAAAAAAAAAEBAQEBAQEBAQEBAQAAAAAAAAAAAAAAAAAAAAAAAAAAAQEBAQEBAQEBAQEBAAAAAAAAAAAAAAAAAAAAAAAAAAABAQEBAQEBAQEBAQEAAAAAAAAAAAAAAAAAAAAAAAAAAAEBAQEBAQEBAQEBAQAAAAAAAAAAAAAAAAAAAAAAAAAAAQEBAQEBAQEBAQEBAAAAAAAAAAAAAAAAAAAAAAAAAAABAQEBAQEBAQEBAQEAAAAAAAAAAAAAAAAAAAAAAAAAAAEBAQEBAQEBAQEBAQAAAAAAAAAAAAAAAAAAAQEBAQEBAQEBAQEBAQEBAQEBAAAAAAAAAAAAAAAAAAABAQEBAQEBAQEBAQEBAQEBAQEAAAAAAAAAAAAAAAAAAAEBAQEBAQEBAQEBAQEBAQEBAQAAAAAAAAAAAAAAAAAAAQEBAQEBAQEBAQEBAAAAAAAAAAAAAAAAAAAAAAAAAAABAQEBAQEBAQEBAQEAAAAAAAAAAAAAAAAAAAAAAAAAAAEBAQEBAQEBAQEBAQAAAAAAAAAAAAAAAAAAAQEBAQEBAQEBAQEBAQEBAQEBAAAAAAAAAAAAAAAAAAABAQEBAQEBAQEBAQEBAQEBAQEAAAAAAAAAAAAAAAAAAAEBAQEBAQEBAQEBAQEBAQEBAQAAAAAAAAAAAAAAAAAAAQEBAQEBAQEBAQEBAQEBAQEBAAAAAAAAAAAAAAAAAAABAQEBAQEBAQEBAQEBAQEBAQEAAAAAAAAAAAAAAAAAAAEBAQEBAQEBAQEBAQ==" - }, - "palette" : { - "originalArgb8888" : [ -265674 ], - "convertedRgb565" : [ -122 ] } }, "diagnostics" : [ ] @@ -618,14 +618,14 @@ "last_modified" : 1774359772445, "fingerprint" : "eeb7cc665386299403b7be1c272375d5077f3647c587f8033aa8c9275f840562", "metadata" : { + "palette" : { + "originalArgb8888" : [ -265674 ], + "convertedRgb565" : [ -122 ] + }, "tile" : { "width" : 32, "height" : 32, "paletteIndices" : "AQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAAAAAAAAAAABAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEAAAAAAAAAAAEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQAAAAAAAAAAAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAAAAAAAAAAABAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEAAAAAAAAAAAEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQAAAAAAAAAAAQEBAQEBAQEBAQEBAAAAAAAAAAAAAAAAAAAAAAAAAAABAQEBAQEBAQEBAQEAAAAAAAAAAAAAAAAAAAAAAAAAAAEBAQEBAQEBAQEBAQAAAAAAAAAAAAAAAAAAAAAAAAAAAQEBAQEBAQEBAQEBAAAAAAAAAAAAAAAAAAAAAAAAAAABAQEBAQEBAQEBAQEAAAAAAAAAAAAAAAAAAAAAAAAAAAEBAQEBAQEBAQEBAQAAAAAAAAAAAAAAAAAAAAAAAAAAAQEBAQEBAQEBAQEBAAAAAAAAAAAAAAAAAAAAAAAAAAABAQEBAQEBAQEBAQEAAAAAAAAAAAAAAAAAAAAAAAAAAAEBAQEBAQEBAQEBAQAAAAAAAAAAAAAAAAAAAQEBAQEBAQEBAQEBAQEBAQEBAAAAAAAAAAAAAAAAAAABAQEBAQEBAQEBAQEBAQEBAQEAAAAAAAAAAAAAAAAAAAEBAQEBAQEBAQEBAQEBAQEBAQAAAAAAAAAAAAAAAAAAAQEBAQEBAQEBAQEBAAAAAAAAAAAAAAAAAAAAAAAAAAABAQEBAQEBAQEBAQEAAAAAAAAAAAAAAAAAAAAAAAAAAAEBAQEBAQEBAQEBAQAAAAAAAAAAAAAAAAAAAQEBAQEBAQEBAQEBAQEBAQEBAAAAAAAAAAAAAAAAAAABAQEBAQEBAQEBAQEBAQEBAQEAAAAAAAAAAAAAAAAAAAEBAQEBAQEBAQEBAQEBAQEBAQAAAAAAAAAAAAAAAAAAAQEBAQEBAQEBAQEBAQEBAQEBAAAAAAAAAAAAAAAAAAABAQEBAQEBAQEBAQEBAQEBAQEAAAAAAAAAAAAAAAAAAAEBAQEBAQEBAQEBAQ==" - }, - "palette" : { - "originalArgb8888" : [ -265674 ], - "convertedRgb565" : [ -122 ] } }, "diagnostics" : [ ] @@ -636,14 +636,14 @@ "last_modified" : 1774359772448, "fingerprint" : "eeb7cc665386299403b7be1c272375d5077f3647c587f8033aa8c9275f840562", "metadata" : { + "palette" : { + "originalArgb8888" : [ -265674 ], + "convertedRgb565" : [ -122 ] + }, "tile" : { "width" : 32, "height" : 32, "paletteIndices" : "AQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAAAAAAAAAAABAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEAAAAAAAAAAAEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQAAAAAAAAAAAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAAAAAAAAAAABAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEAAAAAAAAAAAEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQAAAAAAAAAAAQEBAQEBAQEBAQEBAAAAAAAAAAAAAAAAAAAAAAAAAAABAQEBAQEBAQEBAQEAAAAAAAAAAAAAAAAAAAAAAAAAAAEBAQEBAQEBAQEBAQAAAAAAAAAAAAAAAAAAAAAAAAAAAQEBAQEBAQEBAQEBAAAAAAAAAAAAAAAAAAAAAAAAAAABAQEBAQEBAQEBAQEAAAAAAAAAAAAAAAAAAAAAAAAAAAEBAQEBAQEBAQEBAQAAAAAAAAAAAAAAAAAAAAAAAAAAAQEBAQEBAQEBAQEBAAAAAAAAAAAAAAAAAAAAAAAAAAABAQEBAQEBAQEBAQEAAAAAAAAAAAAAAAAAAAAAAAAAAAEBAQEBAQEBAQEBAQAAAAAAAAAAAAAAAAAAAQEBAQEBAQEBAQEBAQEBAQEBAAAAAAAAAAAAAAAAAAABAQEBAQEBAQEBAQEBAQEBAQEAAAAAAAAAAAAAAAAAAAEBAQEBAQEBAQEBAQEBAQEBAQAAAAAAAAAAAAAAAAAAAQEBAQEBAQEBAQEBAAAAAAAAAAAAAAAAAAAAAAAAAAABAQEBAQEBAQEBAQEAAAAAAAAAAAAAAAAAAAAAAAAAAAEBAQEBAQEBAQEBAQAAAAAAAAAAAAAAAAAAAQEBAQEBAQEBAQEBAQEBAQEBAAAAAAAAAAAAAAAAAAABAQEBAQEBAQEBAQEBAQEBAQEAAAAAAAAAAAAAAAAAAAEBAQEBAQEBAQEBAQEBAQEBAQAAAAAAAAAAAAAAAAAAAQEBAQEBAQEBAQEBAQEBAQEBAAAAAAAAAAAAAAAAAAABAQEBAQEBAQEBAQEBAQEBAQEAAAAAAAAAAAAAAAAAAAEBAQEBAQEBAQEBAQ==" - }, - "palette" : { - "originalArgb8888" : [ -265674 ], - "convertedRgb565" : [ -122 ] } }, "diagnostics" : [ ] @@ -654,14 +654,14 @@ "last_modified" : 1774359772449, "fingerprint" : "eeb7cc665386299403b7be1c272375d5077f3647c587f8033aa8c9275f840562", "metadata" : { + "palette" : { + "originalArgb8888" : [ -265674 ], + "convertedRgb565" : [ -122 ] + }, "tile" : { "width" : 32, "height" : 32, "paletteIndices" : "AQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAAAAAAAAAAABAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEAAAAAAAAAAAEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQAAAAAAAAAAAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAAAAAAAAAAABAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEAAAAAAAAAAAEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQAAAAAAAAAAAQEBAQEBAQEBAQEBAAAAAAAAAAAAAAAAAAAAAAAAAAABAQEBAQEBAQEBAQEAAAAAAAAAAAAAAAAAAAAAAAAAAAEBAQEBAQEBAQEBAQAAAAAAAAAAAAAAAAAAAAAAAAAAAQEBAQEBAQEBAQEBAAAAAAAAAAAAAAAAAAAAAAAAAAABAQEBAQEBAQEBAQEAAAAAAAAAAAAAAAAAAAAAAAAAAAEBAQEBAQEBAQEBAQAAAAAAAAAAAAAAAAAAAAAAAAAAAQEBAQEBAQEBAQEBAAAAAAAAAAAAAAAAAAAAAAAAAAABAQEBAQEBAQEBAQEAAAAAAAAAAAAAAAAAAAAAAAAAAAEBAQEBAQEBAQEBAQAAAAAAAAAAAAAAAAAAAQEBAQEBAQEBAQEBAQEBAQEBAAAAAAAAAAAAAAAAAAABAQEBAQEBAQEBAQEBAQEBAQEAAAAAAAAAAAAAAAAAAAEBAQEBAQEBAQEBAQEBAQEBAQAAAAAAAAAAAAAAAAAAAQEBAQEBAQEBAQEBAAAAAAAAAAAAAAAAAAAAAAAAAAABAQEBAQEBAQEBAQEAAAAAAAAAAAAAAAAAAAAAAAAAAAEBAQEBAQEBAQEBAQAAAAAAAAAAAAAAAAAAAQEBAQEBAQEBAQEBAQEBAQEBAAAAAAAAAAAAAAAAAAABAQEBAQEBAQEBAQEBAQEBAQEAAAAAAAAAAAAAAAAAAAEBAQEBAQEBAQEBAQEBAQEBAQAAAAAAAAAAAAAAAAAAAQEBAQEBAQEBAQEBAQEBAQEBAAAAAAAAAAAAAAAAAAABAQEBAQEBAQEBAQEBAQEBAQEAAAAAAAAAAAAAAAAAAAEBAQEBAQEBAQEBAQ==" - }, - "palette" : { - "originalArgb8888" : [ -265674 ], - "convertedRgb565" : [ -122 ] } }, "diagnostics" : [ ] @@ -672,14 +672,14 @@ "last_modified" : 1774359772450, "fingerprint" : "eeb7cc665386299403b7be1c272375d5077f3647c587f8033aa8c9275f840562", "metadata" : { + "palette" : { + "originalArgb8888" : [ -265674 ], + "convertedRgb565" : [ -122 ] + }, "tile" : { "width" : 32, "height" : 32, "paletteIndices" : "AQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAAAAAAAAAAABAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEAAAAAAAAAAAEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQAAAAAAAAAAAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAAAAAAAAAAABAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEAAAAAAAAAAAEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQAAAAAAAAAAAQEBAQEBAQEBAQEBAAAAAAAAAAAAAAAAAAAAAAAAAAABAQEBAQEBAQEBAQEAAAAAAAAAAAAAAAAAAAAAAAAAAAEBAQEBAQEBAQEBAQAAAAAAAAAAAAAAAAAAAAAAAAAAAQEBAQEBAQEBAQEBAAAAAAAAAAAAAAAAAAAAAAAAAAABAQEBAQEBAQEBAQEAAAAAAAAAAAAAAAAAAAAAAAAAAAEBAQEBAQEBAQEBAQAAAAAAAAAAAAAAAAAAAAAAAAAAAQEBAQEBAQEBAQEBAAAAAAAAAAAAAAAAAAAAAAAAAAABAQEBAQEBAQEBAQEAAAAAAAAAAAAAAAAAAAAAAAAAAAEBAQEBAQEBAQEBAQAAAAAAAAAAAAAAAAAAAQEBAQEBAQEBAQEBAQEBAQEBAAAAAAAAAAAAAAAAAAABAQEBAQEBAQEBAQEBAQEBAQEAAAAAAAAAAAAAAAAAAAEBAQEBAQEBAQEBAQEBAQEBAQAAAAAAAAAAAAAAAAAAAQEBAQEBAQEBAQEBAAAAAAAAAAAAAAAAAAAAAAAAAAABAQEBAQEBAQEBAQEAAAAAAAAAAAAAAAAAAAAAAAAAAAEBAQEBAQEBAQEBAQAAAAAAAAAAAAAAAAAAAQEBAQEBAQEBAQEBAQEBAQEBAAAAAAAAAAAAAAAAAAABAQEBAQEBAQEBAQEBAQEBAQEAAAAAAAAAAAAAAAAAAAEBAQEBAQEBAQEBAQEBAQEBAQAAAAAAAAAAAAAAAAAAAQEBAQEBAQEBAQEBAQEBAQEBAAAAAAAAAAAAAAAAAAABAQEBAQEBAQEBAQEBAQEBAQEAAAAAAAAAAAAAAAAAAAEBAQEBAQEBAQEBAQ==" - }, - "palette" : { - "originalArgb8888" : [ -265674 ], - "convertedRgb565" : [ -122 ] } }, "diagnostics" : [ ] @@ -690,14 +690,14 @@ "last_modified" : 1774359772452, "fingerprint" : "eeb7cc665386299403b7be1c272375d5077f3647c587f8033aa8c9275f840562", "metadata" : { + "palette" : { + "originalArgb8888" : [ -265674 ], + "convertedRgb565" : [ -122 ] + }, "tile" : { "width" : 32, "height" : 32, "paletteIndices" : "AQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAAAAAAAAAAABAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEAAAAAAAAAAAEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQAAAAAAAAAAAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAAAAAAAAAAABAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEAAAAAAAAAAAEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQAAAAAAAAAAAQEBAQEBAQEBAQEBAAAAAAAAAAAAAAAAAAAAAAAAAAABAQEBAQEBAQEBAQEAAAAAAAAAAAAAAAAAAAAAAAAAAAEBAQEBAQEBAQEBAQAAAAAAAAAAAAAAAAAAAAAAAAAAAQEBAQEBAQEBAQEBAAAAAAAAAAAAAAAAAAAAAAAAAAABAQEBAQEBAQEBAQEAAAAAAAAAAAAAAAAAAAAAAAAAAAEBAQEBAQEBAQEBAQAAAAAAAAAAAAAAAAAAAAAAAAAAAQEBAQEBAQEBAQEBAAAAAAAAAAAAAAAAAAAAAAAAAAABAQEBAQEBAQEBAQEAAAAAAAAAAAAAAAAAAAAAAAAAAAEBAQEBAQEBAQEBAQAAAAAAAAAAAAAAAAAAAQEBAQEBAQEBAQEBAQEBAQEBAAAAAAAAAAAAAAAAAAABAQEBAQEBAQEBAQEBAQEBAQEAAAAAAAAAAAAAAAAAAAEBAQEBAQEBAQEBAQEBAQEBAQAAAAAAAAAAAAAAAAAAAQEBAQEBAQEBAQEBAAAAAAAAAAAAAAAAAAAAAAAAAAABAQEBAQEBAQEBAQEAAAAAAAAAAAAAAAAAAAAAAAAAAAEBAQEBAQEBAQEBAQAAAAAAAAAAAAAAAAAAAQEBAQEBAQEBAQEBAQEBAQEBAAAAAAAAAAAAAAAAAAABAQEBAQEBAQEBAQEBAQEBAQEAAAAAAAAAAAAAAAAAAAEBAQEBAQEBAQEBAQEBAQEBAQAAAAAAAAAAAAAAAAAAAQEBAQEBAQEBAQEBAQEBAQEBAAAAAAAAAAAAAAAAAAABAQEBAQEBAQEBAQEBAQEBAQEAAAAAAAAAAAAAAAAAAAEBAQEBAQEBAQEBAQ==" - }, - "palette" : { - "originalArgb8888" : [ -265674 ], - "convertedRgb565" : [ -122 ] } }, "diagnostics" : [ ] @@ -708,14 +708,14 @@ "last_modified" : 1774359772453, "fingerprint" : "eeb7cc665386299403b7be1c272375d5077f3647c587f8033aa8c9275f840562", "metadata" : { + "palette" : { + "originalArgb8888" : [ -265674 ], + "convertedRgb565" : [ -122 ] + }, "tile" : { "width" : 32, "height" : 32, "paletteIndices" : "AQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAAAAAAAAAAABAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEAAAAAAAAAAAEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQAAAAAAAAAAAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAAAAAAAAAAABAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEAAAAAAAAAAAEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQAAAAAAAAAAAQEBAQEBAQEBAQEBAAAAAAAAAAAAAAAAAAAAAAAAAAABAQEBAQEBAQEBAQEAAAAAAAAAAAAAAAAAAAAAAAAAAAEBAQEBAQEBAQEBAQAAAAAAAAAAAAAAAAAAAAAAAAAAAQEBAQEBAQEBAQEBAAAAAAAAAAAAAAAAAAAAAAAAAAABAQEBAQEBAQEBAQEAAAAAAAAAAAAAAAAAAAAAAAAAAAEBAQEBAQEBAQEBAQAAAAAAAAAAAAAAAAAAAAAAAAAAAQEBAQEBAQEBAQEBAAAAAAAAAAAAAAAAAAAAAAAAAAABAQEBAQEBAQEBAQEAAAAAAAAAAAAAAAAAAAAAAAAAAAEBAQEBAQEBAQEBAQAAAAAAAAAAAAAAAAAAAQEBAQEBAQEBAQEBAQEBAQEBAAAAAAAAAAAAAAAAAAABAQEBAQEBAQEBAQEBAQEBAQEAAAAAAAAAAAAAAAAAAAEBAQEBAQEBAQEBAQEBAQEBAQAAAAAAAAAAAAAAAAAAAQEBAQEBAQEBAQEBAAAAAAAAAAAAAAAAAAAAAAAAAAABAQEBAQEBAQEBAQEAAAAAAAAAAAAAAAAAAAAAAAAAAAEBAQEBAQEBAQEBAQAAAAAAAAAAAAAAAAAAAQEBAQEBAQEBAQEBAQEBAQEBAAAAAAAAAAAAAAAAAAABAQEBAQEBAQEBAQEBAQEBAQEAAAAAAAAAAAAAAAAAAAEBAQEBAQEBAQEBAQEBAQEBAQAAAAAAAAAAAAAAAAAAAQEBAQEBAQEBAQEBAQEBAQEBAAAAAAAAAAAAAAAAAAABAQEBAQEBAQEBAQEBAQEBAQEAAAAAAAAAAAAAAAAAAAEBAQEBAQEBAQEBAQ==" - }, - "palette" : { - "originalArgb8888" : [ -265674 ], - "convertedRgb565" : [ -122 ] } }, "diagnostics" : [ ] @@ -726,14 +726,14 @@ "last_modified" : 1774359772454, "fingerprint" : "eeb7cc665386299403b7be1c272375d5077f3647c587f8033aa8c9275f840562", "metadata" : { + "palette" : { + "originalArgb8888" : [ -265674 ], + "convertedRgb565" : [ -122 ] + }, "tile" : { "width" : 32, "height" : 32, "paletteIndices" : "AQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAAAAAAAAAAABAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEAAAAAAAAAAAEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQAAAAAAAAAAAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAAAAAAAAAAABAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEAAAAAAAAAAAEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQAAAAAAAAAAAQEBAQEBAQEBAQEBAAAAAAAAAAAAAAAAAAAAAAAAAAABAQEBAQEBAQEBAQEAAAAAAAAAAAAAAAAAAAAAAAAAAAEBAQEBAQEBAQEBAQAAAAAAAAAAAAAAAAAAAAAAAAAAAQEBAQEBAQEBAQEBAAAAAAAAAAAAAAAAAAAAAAAAAAABAQEBAQEBAQEBAQEAAAAAAAAAAAAAAAAAAAAAAAAAAAEBAQEBAQEBAQEBAQAAAAAAAAAAAAAAAAAAAAAAAAAAAQEBAQEBAQEBAQEBAAAAAAAAAAAAAAAAAAAAAAAAAAABAQEBAQEBAQEBAQEAAAAAAAAAAAAAAAAAAAAAAAAAAAEBAQEBAQEBAQEBAQAAAAAAAAAAAAAAAAAAAQEBAQEBAQEBAQEBAQEBAQEBAAAAAAAAAAAAAAAAAAABAQEBAQEBAQEBAQEBAQEBAQEAAAAAAAAAAAAAAAAAAAEBAQEBAQEBAQEBAQEBAQEBAQAAAAAAAAAAAAAAAAAAAQEBAQEBAQEBAQEBAAAAAAAAAAAAAAAAAAAAAAAAAAABAQEBAQEBAQEBAQEAAAAAAAAAAAAAAAAAAAAAAAAAAAEBAQEBAQEBAQEBAQAAAAAAAAAAAAAAAAAAAQEBAQEBAQEBAQEBAQEBAQEBAAAAAAAAAAAAAAAAAAABAQEBAQEBAQEBAQEBAQEBAQEAAAAAAAAAAAAAAAAAAAEBAQEBAQEBAQEBAQEBAQEBAQAAAAAAAAAAAAAAAAAAAQEBAQEBAQEBAQEBAQEBAQEBAAAAAAAAAAAAAAAAAAABAQEBAQEBAQEBAQEBAQEBAQEAAAAAAAAAAAAAAAAAAAEBAQEBAQEBAQEBAQ==" - }, - "palette" : { - "originalArgb8888" : [ -265674 ], - "convertedRgb565" : [ -122 ] } }, "diagnostics" : [ ] @@ -744,14 +744,14 @@ "last_modified" : 1774359772455, "fingerprint" : "eeb7cc665386299403b7be1c272375d5077f3647c587f8033aa8c9275f840562", "metadata" : { + "palette" : { + "originalArgb8888" : [ -265674 ], + "convertedRgb565" : [ -122 ] + }, "tile" : { "width" : 32, "height" : 32, "paletteIndices" : "AQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAAAAAAAAAAABAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEAAAAAAAAAAAEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQAAAAAAAAAAAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAAAAAAAAAAABAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEAAAAAAAAAAAEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQAAAAAAAAAAAQEBAQEBAQEBAQEBAAAAAAAAAAAAAAAAAAAAAAAAAAABAQEBAQEBAQEBAQEAAAAAAAAAAAAAAAAAAAAAAAAAAAEBAQEBAQEBAQEBAQAAAAAAAAAAAAAAAAAAAAAAAAAAAQEBAQEBAQEBAQEBAAAAAAAAAAAAAAAAAAAAAAAAAAABAQEBAQEBAQEBAQEAAAAAAAAAAAAAAAAAAAAAAAAAAAEBAQEBAQEBAQEBAQAAAAAAAAAAAAAAAAAAAAAAAAAAAQEBAQEBAQEBAQEBAAAAAAAAAAAAAAAAAAAAAAAAAAABAQEBAQEBAQEBAQEAAAAAAAAAAAAAAAAAAAAAAAAAAAEBAQEBAQEBAQEBAQAAAAAAAAAAAAAAAAAAAQEBAQEBAQEBAQEBAQEBAQEBAAAAAAAAAAAAAAAAAAABAQEBAQEBAQEBAQEBAQEBAQEAAAAAAAAAAAAAAAAAAAEBAQEBAQEBAQEBAQEBAQEBAQAAAAAAAAAAAAAAAAAAAQEBAQEBAQEBAQEBAAAAAAAAAAAAAAAAAAAAAAAAAAABAQEBAQEBAQEBAQEAAAAAAAAAAAAAAAAAAAAAAAAAAAEBAQEBAQEBAQEBAQAAAAAAAAAAAAAAAAAAAQEBAQEBAQEBAQEBAQEBAQEBAAAAAAAAAAAAAAAAAAABAQEBAQEBAQEBAQEBAQEBAQEAAAAAAAAAAAAAAAAAAAEBAQEBAQEBAQEBAQEBAQEBAQAAAAAAAAAAAAAAAAAAAQEBAQEBAQEBAQEBAQEBAQEBAAAAAAAAAAAAAAAAAAABAQEBAQEBAQEBAQEBAQEBAQEAAAAAAAAAAAAAAAAAAAEBAQEBAQEBAQEBAQ==" - }, - "palette" : { - "originalArgb8888" : [ -265674 ], - "convertedRgb565" : [ -122 ] } }, "diagnostics" : [ ] @@ -762,14 +762,14 @@ "last_modified" : 1774359772456, "fingerprint" : "eeb7cc665386299403b7be1c272375d5077f3647c587f8033aa8c9275f840562", "metadata" : { + "palette" : { + "originalArgb8888" : [ -265674 ], + "convertedRgb565" : [ -122 ] + }, "tile" : { "width" : 32, "height" : 32, "paletteIndices" : "AQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAAAAAAAAAAABAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEAAAAAAAAAAAEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQAAAAAAAAAAAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAAAAAAAAAAABAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEAAAAAAAAAAAEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQAAAAAAAAAAAQEBAQEBAQEBAQEBAAAAAAAAAAAAAAAAAAAAAAAAAAABAQEBAQEBAQEBAQEAAAAAAAAAAAAAAAAAAAAAAAAAAAEBAQEBAQEBAQEBAQAAAAAAAAAAAAAAAAAAAAAAAAAAAQEBAQEBAQEBAQEBAAAAAAAAAAAAAAAAAAAAAAAAAAABAQEBAQEBAQEBAQEAAAAAAAAAAAAAAAAAAAAAAAAAAAEBAQEBAQEBAQEBAQAAAAAAAAAAAAAAAAAAAAAAAAAAAQEBAQEBAQEBAQEBAAAAAAAAAAAAAAAAAAAAAAAAAAABAQEBAQEBAQEBAQEAAAAAAAAAAAAAAAAAAAAAAAAAAAEBAQEBAQEBAQEBAQAAAAAAAAAAAAAAAAAAAQEBAQEBAQEBAQEBAQEBAQEBAAAAAAAAAAAAAAAAAAABAQEBAQEBAQEBAQEBAQEBAQEAAAAAAAAAAAAAAAAAAAEBAQEBAQEBAQEBAQEBAQEBAQAAAAAAAAAAAAAAAAAAAQEBAQEBAQEBAQEBAAAAAAAAAAAAAAAAAAAAAAAAAAABAQEBAQEBAQEBAQEAAAAAAAAAAAAAAAAAAAAAAAAAAAEBAQEBAQEBAQEBAQAAAAAAAAAAAAAAAAAAAQEBAQEBAQEBAQEBAQEBAQEBAAAAAAAAAAAAAAAAAAABAQEBAQEBAQEBAQEBAQEBAQEAAAAAAAAAAAAAAAAAAAEBAQEBAQEBAQEBAQEBAQEBAQAAAAAAAAAAAAAAAAAAAQEBAQEBAQEBAQEBAQEBAQEBAAAAAAAAAAAAAAAAAAABAQEBAQEBAQEBAQEBAQEBAQEAAAAAAAAAAAAAAAAAAAEBAQEBAQEBAQEBAQ==" - }, - "palette" : { - "originalArgb8888" : [ -265674 ], - "convertedRgb565" : [ -122 ] } }, "diagnostics" : [ ] @@ -780,14 +780,14 @@ "last_modified" : 1774359772458, "fingerprint" : "eeb7cc665386299403b7be1c272375d5077f3647c587f8033aa8c9275f840562", "metadata" : { + "palette" : { + "originalArgb8888" : [ -265674 ], + "convertedRgb565" : [ -122 ] + }, "tile" : { "width" : 32, "height" : 32, "paletteIndices" : "AQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAAAAAAAAAAABAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEAAAAAAAAAAAEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQAAAAAAAAAAAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAAAAAAAAAAABAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEAAAAAAAAAAAEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQAAAAAAAAAAAQEBAQEBAQEBAQEBAAAAAAAAAAAAAAAAAAAAAAAAAAABAQEBAQEBAQEBAQEAAAAAAAAAAAAAAAAAAAAAAAAAAAEBAQEBAQEBAQEBAQAAAAAAAAAAAAAAAAAAAAAAAAAAAQEBAQEBAQEBAQEBAAAAAAAAAAAAAAAAAAAAAAAAAAABAQEBAQEBAQEBAQEAAAAAAAAAAAAAAAAAAAAAAAAAAAEBAQEBAQEBAQEBAQAAAAAAAAAAAAAAAAAAAAAAAAAAAQEBAQEBAQEBAQEBAAAAAAAAAAAAAAAAAAAAAAAAAAABAQEBAQEBAQEBAQEAAAAAAAAAAAAAAAAAAAAAAAAAAAEBAQEBAQEBAQEBAQAAAAAAAAAAAAAAAAAAAQEBAQEBAQEBAQEBAQEBAQEBAAAAAAAAAAAAAAAAAAABAQEBAQEBAQEBAQEBAQEBAQEAAAAAAAAAAAAAAAAAAAEBAQEBAQEBAQEBAQEBAQEBAQAAAAAAAAAAAAAAAAAAAQEBAQEBAQEBAQEBAAAAAAAAAAAAAAAAAAAAAAAAAAABAQEBAQEBAQEBAQEAAAAAAAAAAAAAAAAAAAAAAAAAAAEBAQEBAQEBAQEBAQAAAAAAAAAAAAAAAAAAAQEBAQEBAQEBAQEBAQEBAQEBAAAAAAAAAAAAAAAAAAABAQEBAQEBAQEBAQEBAQEBAQEAAAAAAAAAAAAAAAAAAAEBAQEBAQEBAQEBAQEBAQEBAQAAAAAAAAAAAAAAAAAAAQEBAQEBAQEBAQEBAQEBAQEBAAAAAAAAAAAAAAAAAAABAQEBAQEBAQEBAQEBAQEBAQEAAAAAAAAAAAAAAAAAAAEBAQEBAQEBAQEBAQ==" - }, - "palette" : { - "originalArgb8888" : [ -265674 ], - "convertedRgb565" : [ -122 ] } }, "diagnostics" : [ ] @@ -798,14 +798,14 @@ "last_modified" : 1774359772459, "fingerprint" : "eeb7cc665386299403b7be1c272375d5077f3647c587f8033aa8c9275f840562", "metadata" : { + "palette" : { + "originalArgb8888" : [ -265674 ], + "convertedRgb565" : [ -122 ] + }, "tile" : { "width" : 32, "height" : 32, "paletteIndices" : "AQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAAAAAAAAAAABAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEAAAAAAAAAAAEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQAAAAAAAAAAAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAAAAAAAAAAABAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEAAAAAAAAAAAEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQAAAAAAAAAAAQEBAQEBAQEBAQEBAAAAAAAAAAAAAAAAAAAAAAAAAAABAQEBAQEBAQEBAQEAAAAAAAAAAAAAAAAAAAAAAAAAAAEBAQEBAQEBAQEBAQAAAAAAAAAAAAAAAAAAAAAAAAAAAQEBAQEBAQEBAQEBAAAAAAAAAAAAAAAAAAAAAAAAAAABAQEBAQEBAQEBAQEAAAAAAAAAAAAAAAAAAAAAAAAAAAEBAQEBAQEBAQEBAQAAAAAAAAAAAAAAAAAAAAAAAAAAAQEBAQEBAQEBAQEBAAAAAAAAAAAAAAAAAAAAAAAAAAABAQEBAQEBAQEBAQEAAAAAAAAAAAAAAAAAAAAAAAAAAAEBAQEBAQEBAQEBAQAAAAAAAAAAAAAAAAAAAQEBAQEBAQEBAQEBAQEBAQEBAAAAAAAAAAAAAAAAAAABAQEBAQEBAQEBAQEBAQEBAQEAAAAAAAAAAAAAAAAAAAEBAQEBAQEBAQEBAQEBAQEBAQAAAAAAAAAAAAAAAAAAAQEBAQEBAQEBAQEBAAAAAAAAAAAAAAAAAAAAAAAAAAABAQEBAQEBAQEBAQEAAAAAAAAAAAAAAAAAAAAAAAAAAAEBAQEBAQEBAQEBAQAAAAAAAAAAAAAAAAAAAQEBAQEBAQEBAQEBAQEBAQEBAAAAAAAAAAAAAAAAAAABAQEBAQEBAQEBAQEBAQEBAQEAAAAAAAAAAAAAAAAAAAEBAQEBAQEBAQEBAQEBAQEBAQAAAAAAAAAAAAAAAAAAAQEBAQEBAQEBAQEBAQEBAQEBAAAAAAAAAAAAAAAAAAABAQEBAQEBAQEBAQEBAQEBAQEAAAAAAAAAAAAAAAAAAAEBAQEBAQEBAQEBAQ==" - }, - "palette" : { - "originalArgb8888" : [ -265674 ], - "convertedRgb565" : [ -122 ] } }, "diagnostics" : [ ] @@ -816,14 +816,14 @@ "last_modified" : 1774359772460, "fingerprint" : "eeb7cc665386299403b7be1c272375d5077f3647c587f8033aa8c9275f840562", "metadata" : { + "palette" : { + "originalArgb8888" : [ -265674 ], + "convertedRgb565" : [ -122 ] + }, "tile" : { "width" : 32, "height" : 32, "paletteIndices" : "AQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAAAAAAAAAAABAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEAAAAAAAAAAAEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQAAAAAAAAAAAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAAAAAAAAAAABAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEAAAAAAAAAAAEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQAAAAAAAAAAAQEBAQEBAQEBAQEBAAAAAAAAAAAAAAAAAAAAAAAAAAABAQEBAQEBAQEBAQEAAAAAAAAAAAAAAAAAAAAAAAAAAAEBAQEBAQEBAQEBAQAAAAAAAAAAAAAAAAAAAAAAAAAAAQEBAQEBAQEBAQEBAAAAAAAAAAAAAAAAAAAAAAAAAAABAQEBAQEBAQEBAQEAAAAAAAAAAAAAAAAAAAAAAAAAAAEBAQEBAQEBAQEBAQAAAAAAAAAAAAAAAAAAAAAAAAAAAQEBAQEBAQEBAQEBAAAAAAAAAAAAAAAAAAAAAAAAAAABAQEBAQEBAQEBAQEAAAAAAAAAAAAAAAAAAAAAAAAAAAEBAQEBAQEBAQEBAQAAAAAAAAAAAAAAAAAAAQEBAQEBAQEBAQEBAQEBAQEBAAAAAAAAAAAAAAAAAAABAQEBAQEBAQEBAQEBAQEBAQEAAAAAAAAAAAAAAAAAAAEBAQEBAQEBAQEBAQEBAQEBAQAAAAAAAAAAAAAAAAAAAQEBAQEBAQEBAQEBAAAAAAAAAAAAAAAAAAAAAAAAAAABAQEBAQEBAQEBAQEAAAAAAAAAAAAAAAAAAAAAAAAAAAEBAQEBAQEBAQEBAQAAAAAAAAAAAAAAAAAAAQEBAQEBAQEBAQEBAQEBAQEBAAAAAAAAAAAAAAAAAAABAQEBAQEBAQEBAQEBAQEBAQEAAAAAAAAAAAAAAAAAAAEBAQEBAQEBAQEBAQEBAQEBAQAAAAAAAAAAAAAAAAAAAQEBAQEBAQEBAQEBAQEBAQEBAAAAAAAAAAAAAAAAAAABAQEBAQEBAQEBAQEBAQEBAQEAAAAAAAAAAAAAAAAAAAEBAQEBAQEBAQEBAQ==" - }, - "palette" : { - "originalArgb8888" : [ -265674 ], - "convertedRgb565" : [ -122 ] } }, "diagnostics" : [ ] @@ -834,14 +834,14 @@ "last_modified" : 1774359772461, "fingerprint" : "eeb7cc665386299403b7be1c272375d5077f3647c587f8033aa8c9275f840562", "metadata" : { + "palette" : { + "originalArgb8888" : [ -265674 ], + "convertedRgb565" : [ -122 ] + }, "tile" : { "width" : 32, "height" : 32, "paletteIndices" : "AQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAAAAAAAAAAABAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEAAAAAAAAAAAEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQAAAAAAAAAAAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAAAAAAAAAAABAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEAAAAAAAAAAAEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQAAAAAAAAAAAQEBAQEBAQEBAQEBAAAAAAAAAAAAAAAAAAAAAAAAAAABAQEBAQEBAQEBAQEAAAAAAAAAAAAAAAAAAAAAAAAAAAEBAQEBAQEBAQEBAQAAAAAAAAAAAAAAAAAAAAAAAAAAAQEBAQEBAQEBAQEBAAAAAAAAAAAAAAAAAAAAAAAAAAABAQEBAQEBAQEBAQEAAAAAAAAAAAAAAAAAAAAAAAAAAAEBAQEBAQEBAQEBAQAAAAAAAAAAAAAAAAAAAAAAAAAAAQEBAQEBAQEBAQEBAAAAAAAAAAAAAAAAAAAAAAAAAAABAQEBAQEBAQEBAQEAAAAAAAAAAAAAAAAAAAAAAAAAAAEBAQEBAQEBAQEBAQAAAAAAAAAAAAAAAAAAAQEBAQEBAQEBAQEBAQEBAQEBAAAAAAAAAAAAAAAAAAABAQEBAQEBAQEBAQEBAQEBAQEAAAAAAAAAAAAAAAAAAAEBAQEBAQEBAQEBAQEBAQEBAQAAAAAAAAAAAAAAAAAAAQEBAQEBAQEBAQEBAAAAAAAAAAAAAAAAAAAAAAAAAAABAQEBAQEBAQEBAQEAAAAAAAAAAAAAAAAAAAAAAAAAAAEBAQEBAQEBAQEBAQAAAAAAAAAAAAAAAAAAAQEBAQEBAQEBAQEBAQEBAQEBAAAAAAAAAAAAAAAAAAABAQEBAQEBAQEBAQEBAQEBAQEAAAAAAAAAAAAAAAAAAAEBAQEBAQEBAQEBAQEBAQEBAQAAAAAAAAAAAAAAAAAAAQEBAQEBAQEBAQEBAQEBAQEBAAAAAAAAAAAAAAAAAAABAQEBAQEBAQEBAQEBAQEBAQEAAAAAAAAAAAAAAAAAAAEBAQEBAQEBAQEBAQ==" - }, - "palette" : { - "originalArgb8888" : [ -265674 ], - "convertedRgb565" : [ -122 ] } }, "diagnostics" : [ ] @@ -852,14 +852,14 @@ "last_modified" : 1774359772463, "fingerprint" : "eeb7cc665386299403b7be1c272375d5077f3647c587f8033aa8c9275f840562", "metadata" : { + "palette" : { + "originalArgb8888" : [ -265674 ], + "convertedRgb565" : [ -122 ] + }, "tile" : { "width" : 32, "height" : 32, "paletteIndices" : "AQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAAAAAAAAAAABAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEAAAAAAAAAAAEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQAAAAAAAAAAAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAAAAAAAAAAABAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEAAAAAAAAAAAEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQAAAAAAAAAAAQEBAQEBAQEBAQEBAAAAAAAAAAAAAAAAAAAAAAAAAAABAQEBAQEBAQEBAQEAAAAAAAAAAAAAAAAAAAAAAAAAAAEBAQEBAQEBAQEBAQAAAAAAAAAAAAAAAAAAAAAAAAAAAQEBAQEBAQEBAQEBAAAAAAAAAAAAAAAAAAAAAAAAAAABAQEBAQEBAQEBAQEAAAAAAAAAAAAAAAAAAAAAAAAAAAEBAQEBAQEBAQEBAQAAAAAAAAAAAAAAAAAAAAAAAAAAAQEBAQEBAQEBAQEBAAAAAAAAAAAAAAAAAAAAAAAAAAABAQEBAQEBAQEBAQEAAAAAAAAAAAAAAAAAAAAAAAAAAAEBAQEBAQEBAQEBAQAAAAAAAAAAAAAAAAAAAQEBAQEBAQEBAQEBAQEBAQEBAAAAAAAAAAAAAAAAAAABAQEBAQEBAQEBAQEBAQEBAQEAAAAAAAAAAAAAAAAAAAEBAQEBAQEBAQEBAQEBAQEBAQAAAAAAAAAAAAAAAAAAAQEBAQEBAQEBAQEBAAAAAAAAAAAAAAAAAAAAAAAAAAABAQEBAQEBAQEBAQEAAAAAAAAAAAAAAAAAAAAAAAAAAAEBAQEBAQEBAQEBAQAAAAAAAAAAAAAAAAAAAQEBAQEBAQEBAQEBAQEBAQEBAAAAAAAAAAAAAAAAAAABAQEBAQEBAQEBAQEBAQEBAQEAAAAAAAAAAAAAAAAAAAEBAQEBAQEBAQEBAQEBAQEBAQAAAAAAAAAAAAAAAAAAAQEBAQEBAQEBAQEBAQEBAQEBAAAAAAAAAAAAAAAAAAABAQEBAQEBAQEBAQEBAQEBAQEAAAAAAAAAAAAAAAAAAAEBAQEBAQEBAQEBAQ==" - }, - "palette" : { - "originalArgb8888" : [ -265674 ], - "convertedRgb565" : [ -122 ] } }, "diagnostics" : [ ] @@ -870,14 +870,14 @@ "last_modified" : 1774359772464, "fingerprint" : "eeb7cc665386299403b7be1c272375d5077f3647c587f8033aa8c9275f840562", "metadata" : { + "palette" : { + "originalArgb8888" : [ -265674 ], + "convertedRgb565" : [ -122 ] + }, "tile" : { "width" : 32, "height" : 32, "paletteIndices" : "AQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAAAAAAAAAAABAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEAAAAAAAAAAAEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQAAAAAAAAAAAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAAAAAAAAAAABAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEAAAAAAAAAAAEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQAAAAAAAAAAAQEBAQEBAQEBAQEBAAAAAAAAAAAAAAAAAAAAAAAAAAABAQEBAQEBAQEBAQEAAAAAAAAAAAAAAAAAAAAAAAAAAAEBAQEBAQEBAQEBAQAAAAAAAAAAAAAAAAAAAAAAAAAAAQEBAQEBAQEBAQEBAAAAAAAAAAAAAAAAAAAAAAAAAAABAQEBAQEBAQEBAQEAAAAAAAAAAAAAAAAAAAAAAAAAAAEBAQEBAQEBAQEBAQAAAAAAAAAAAAAAAAAAAAAAAAAAAQEBAQEBAQEBAQEBAAAAAAAAAAAAAAAAAAAAAAAAAAABAQEBAQEBAQEBAQEAAAAAAAAAAAAAAAAAAAAAAAAAAAEBAQEBAQEBAQEBAQAAAAAAAAAAAAAAAAAAAQEBAQEBAQEBAQEBAQEBAQEBAAAAAAAAAAAAAAAAAAABAQEBAQEBAQEBAQEBAQEBAQEAAAAAAAAAAAAAAAAAAAEBAQEBAQEBAQEBAQEBAQEBAQAAAAAAAAAAAAAAAAAAAQEBAQEBAQEBAQEBAAAAAAAAAAAAAAAAAAAAAAAAAAABAQEBAQEBAQEBAQEAAAAAAAAAAAAAAAAAAAAAAAAAAAEBAQEBAQEBAQEBAQAAAAAAAAAAAAAAAAAAAQEBAQEBAQEBAQEBAQEBAQEBAAAAAAAAAAAAAAAAAAABAQEBAQEBAQEBAQEBAQEBAQEAAAAAAAAAAAAAAAAAAAEBAQEBAQEBAQEBAQEBAQEBAQAAAAAAAAAAAAAAAAAAAQEBAQEBAQEBAQEBAQEBAQEBAAAAAAAAAAAAAAAAAAABAQEBAQEBAQEBAQEBAQEBAQEAAAAAAAAAAAAAAAAAAAEBAQEBAQEBAQEBAQ==" - }, - "palette" : { - "originalArgb8888" : [ -265674 ], - "convertedRgb565" : [ -122 ] } }, "diagnostics" : [ ] @@ -888,14 +888,14 @@ "last_modified" : 1774359772465, "fingerprint" : "eeb7cc665386299403b7be1c272375d5077f3647c587f8033aa8c9275f840562", "metadata" : { + "palette" : { + "originalArgb8888" : [ -265674 ], + "convertedRgb565" : [ -122 ] + }, "tile" : { "width" : 32, "height" : 32, "paletteIndices" : "AQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAAAAAAAAAAABAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEAAAAAAAAAAAEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQAAAAAAAAAAAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAAAAAAAAAAABAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEAAAAAAAAAAAEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQAAAAAAAAAAAQEBAQEBAQEBAQEBAAAAAAAAAAAAAAAAAAAAAAAAAAABAQEBAQEBAQEBAQEAAAAAAAAAAAAAAAAAAAAAAAAAAAEBAQEBAQEBAQEBAQAAAAAAAAAAAAAAAAAAAAAAAAAAAQEBAQEBAQEBAQEBAAAAAAAAAAAAAAAAAAAAAAAAAAABAQEBAQEBAQEBAQEAAAAAAAAAAAAAAAAAAAAAAAAAAAEBAQEBAQEBAQEBAQAAAAAAAAAAAAAAAAAAAAAAAAAAAQEBAQEBAQEBAQEBAAAAAAAAAAAAAAAAAAAAAAAAAAABAQEBAQEBAQEBAQEAAAAAAAAAAAAAAAAAAAAAAAAAAAEBAQEBAQEBAQEBAQAAAAAAAAAAAAAAAAAAAQEBAQEBAQEBAQEBAQEBAQEBAAAAAAAAAAAAAAAAAAABAQEBAQEBAQEBAQEBAQEBAQEAAAAAAAAAAAAAAAAAAAEBAQEBAQEBAQEBAQEBAQEBAQAAAAAAAAAAAAAAAAAAAQEBAQEBAQEBAQEBAAAAAAAAAAAAAAAAAAAAAAAAAAABAQEBAQEBAQEBAQEAAAAAAAAAAAAAAAAAAAAAAAAAAAEBAQEBAQEBAQEBAQAAAAAAAAAAAAAAAAAAAQEBAQEBAQEBAQEBAQEBAQEBAAAAAAAAAAAAAAAAAAABAQEBAQEBAQEBAQEBAQEBAQEAAAAAAAAAAAAAAAAAAAEBAQEBAQEBAQEBAQEBAQEBAQAAAAAAAAAAAAAAAAAAAQEBAQEBAQEBAQEBAQEBAQEBAAAAAAAAAAAAAAAAAAABAQEBAQEBAQEBAQEBAQEBAQEAAAAAAAAAAAAAAAAAAAEBAQEBAQEBAQEBAQ==" - }, - "palette" : { - "originalArgb8888" : [ -265674 ], - "convertedRgb565" : [ -122 ] } }, "diagnostics" : [ ] @@ -906,14 +906,14 @@ "last_modified" : 1774359772467, "fingerprint" : "eeb7cc665386299403b7be1c272375d5077f3647c587f8033aa8c9275f840562", "metadata" : { + "palette" : { + "originalArgb8888" : [ -265674 ], + "convertedRgb565" : [ -122 ] + }, "tile" : { "width" : 32, "height" : 32, "paletteIndices" : "AQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAAAAAAAAAAABAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEAAAAAAAAAAAEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQAAAAAAAAAAAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAAAAAAAAAAABAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEAAAAAAAAAAAEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQAAAAAAAAAAAQEBAQEBAQEBAQEBAAAAAAAAAAAAAAAAAAAAAAAAAAABAQEBAQEBAQEBAQEAAAAAAAAAAAAAAAAAAAAAAAAAAAEBAQEBAQEBAQEBAQAAAAAAAAAAAAAAAAAAAAAAAAAAAQEBAQEBAQEBAQEBAAAAAAAAAAAAAAAAAAAAAAAAAAABAQEBAQEBAQEBAQEAAAAAAAAAAAAAAAAAAAAAAAAAAAEBAQEBAQEBAQEBAQAAAAAAAAAAAAAAAAAAAAAAAAAAAQEBAQEBAQEBAQEBAAAAAAAAAAAAAAAAAAAAAAAAAAABAQEBAQEBAQEBAQEAAAAAAAAAAAAAAAAAAAAAAAAAAAEBAQEBAQEBAQEBAQAAAAAAAAAAAAAAAAAAAQEBAQEBAQEBAQEBAQEBAQEBAAAAAAAAAAAAAAAAAAABAQEBAQEBAQEBAQEBAQEBAQEAAAAAAAAAAAAAAAAAAAEBAQEBAQEBAQEBAQEBAQEBAQAAAAAAAAAAAAAAAAAAAQEBAQEBAQEBAQEBAAAAAAAAAAAAAAAAAAAAAAAAAAABAQEBAQEBAQEBAQEAAAAAAAAAAAAAAAAAAAAAAAAAAAEBAQEBAQEBAQEBAQAAAAAAAAAAAAAAAAAAAQEBAQEBAQEBAQEBAQEBAQEBAAAAAAAAAAAAAAAAAAABAQEBAQEBAQEBAQEBAQEBAQEAAAAAAAAAAAAAAAAAAAEBAQEBAQEBAQEBAQEBAQEBAQAAAAAAAAAAAAAAAAAAAQEBAQEBAQEBAQEBAQEBAQEBAAAAAAAAAAAAAAAAAAABAQEBAQEBAQEBAQEBAQEBAQEAAAAAAAAAAAAAAAAAAAEBAQEBAQEBAQEBAQ==" - }, - "palette" : { - "originalArgb8888" : [ -265674 ], - "convertedRgb565" : [ -122 ] } }, "diagnostics" : [ ] @@ -924,14 +924,14 @@ "last_modified" : 1774359772468, "fingerprint" : "eeb7cc665386299403b7be1c272375d5077f3647c587f8033aa8c9275f840562", "metadata" : { + "palette" : { + "originalArgb8888" : [ -265674 ], + "convertedRgb565" : [ -122 ] + }, "tile" : { "width" : 32, "height" : 32, "paletteIndices" : "AQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAAAAAAAAAAABAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEAAAAAAAAAAAEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQAAAAAAAAAAAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAAAAAAAAAAABAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEAAAAAAAAAAAEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQAAAAAAAAAAAQEBAQEBAQEBAQEBAAAAAAAAAAAAAAAAAAAAAAAAAAABAQEBAQEBAQEBAQEAAAAAAAAAAAAAAAAAAAAAAAAAAAEBAQEBAQEBAQEBAQAAAAAAAAAAAAAAAAAAAAAAAAAAAQEBAQEBAQEBAQEBAAAAAAAAAAAAAAAAAAAAAAAAAAABAQEBAQEBAQEBAQEAAAAAAAAAAAAAAAAAAAAAAAAAAAEBAQEBAQEBAQEBAQAAAAAAAAAAAAAAAAAAAAAAAAAAAQEBAQEBAQEBAQEBAAAAAAAAAAAAAAAAAAAAAAAAAAABAQEBAQEBAQEBAQEAAAAAAAAAAAAAAAAAAAAAAAAAAAEBAQEBAQEBAQEBAQAAAAAAAAAAAAAAAAAAAQEBAQEBAQEBAQEBAQEBAQEBAAAAAAAAAAAAAAAAAAABAQEBAQEBAQEBAQEBAQEBAQEAAAAAAAAAAAAAAAAAAAEBAQEBAQEBAQEBAQEBAQEBAQAAAAAAAAAAAAAAAAAAAQEBAQEBAQEBAQEBAAAAAAAAAAAAAAAAAAAAAAAAAAABAQEBAQEBAQEBAQEAAAAAAAAAAAAAAAAAAAAAAAAAAAEBAQEBAQEBAQEBAQAAAAAAAAAAAAAAAAAAAQEBAQEBAQEBAQEBAQEBAQEBAAAAAAAAAAAAAAAAAAABAQEBAQEBAQEBAQEBAQEBAQEAAAAAAAAAAAAAAAAAAAEBAQEBAQEBAQEBAQEBAQEBAQAAAAAAAAAAAAAAAAAAAQEBAQEBAQEBAQEBAQEBAQEBAAAAAAAAAAAAAAAAAAABAQEBAQEBAQEBAQEBAQEBAQEAAAAAAAAAAAAAAAAAAAEBAQEBAQEBAQEBAQ==" - }, - "palette" : { - "originalArgb8888" : [ -265674 ], - "convertedRgb565" : [ -122 ] } }, "diagnostics" : [ ] @@ -942,14 +942,14 @@ "last_modified" : 1774359772470, "fingerprint" : "eeb7cc665386299403b7be1c272375d5077f3647c587f8033aa8c9275f840562", "metadata" : { + "palette" : { + "originalArgb8888" : [ -265674 ], + "convertedRgb565" : [ -122 ] + }, "tile" : { "width" : 32, "height" : 32, "paletteIndices" : "AQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAAAAAAAAAAABAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEAAAAAAAAAAAEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQAAAAAAAAAAAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAAAAAAAAAAABAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEAAAAAAAAAAAEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQAAAAAAAAAAAQEBAQEBAQEBAQEBAAAAAAAAAAAAAAAAAAAAAAAAAAABAQEBAQEBAQEBAQEAAAAAAAAAAAAAAAAAAAAAAAAAAAEBAQEBAQEBAQEBAQAAAAAAAAAAAAAAAAAAAAAAAAAAAQEBAQEBAQEBAQEBAAAAAAAAAAAAAAAAAAAAAAAAAAABAQEBAQEBAQEBAQEAAAAAAAAAAAAAAAAAAAAAAAAAAAEBAQEBAQEBAQEBAQAAAAAAAAAAAAAAAAAAAAAAAAAAAQEBAQEBAQEBAQEBAAAAAAAAAAAAAAAAAAAAAAAAAAABAQEBAQEBAQEBAQEAAAAAAAAAAAAAAAAAAAAAAAAAAAEBAQEBAQEBAQEBAQAAAAAAAAAAAAAAAAAAAQEBAQEBAQEBAQEBAQEBAQEBAAAAAAAAAAAAAAAAAAABAQEBAQEBAQEBAQEBAQEBAQEAAAAAAAAAAAAAAAAAAAEBAQEBAQEBAQEBAQEBAQEBAQAAAAAAAAAAAAAAAAAAAQEBAQEBAQEBAQEBAAAAAAAAAAAAAAAAAAAAAAAAAAABAQEBAQEBAQEBAQEAAAAAAAAAAAAAAAAAAAAAAAAAAAEBAQEBAQEBAQEBAQAAAAAAAAAAAAAAAAAAAQEBAQEBAQEBAQEBAQEBAQEBAAAAAAAAAAAAAAAAAAABAQEBAQEBAQEBAQEBAQEBAQEAAAAAAAAAAAAAAAAAAAEBAQEBAQEBAQEBAQEBAQEBAQAAAAAAAAAAAAAAAAAAAQEBAQEBAQEBAQEBAQEBAQEBAAAAAAAAAAAAAAAAAAABAQEBAQEBAQEBAQEBAQEBAQEAAAAAAAAAAAAAAAAAAAEBAQEBAQEBAQEBAQ==" - }, - "palette" : { - "originalArgb8888" : [ -265674 ], - "convertedRgb565" : [ -122 ] } }, "diagnostics" : [ ] @@ -960,14 +960,14 @@ "last_modified" : 1774359772474, "fingerprint" : "eeb7cc665386299403b7be1c272375d5077f3647c587f8033aa8c9275f840562", "metadata" : { + "palette" : { + "originalArgb8888" : [ -265674 ], + "convertedRgb565" : [ -122 ] + }, "tile" : { "width" : 32, "height" : 32, "paletteIndices" : "AQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAAAAAAAAAAABAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEAAAAAAAAAAAEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQAAAAAAAAAAAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAAAAAAAAAAABAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEAAAAAAAAAAAEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQAAAAAAAAAAAQEBAQEBAQEBAQEBAAAAAAAAAAAAAAAAAAAAAAAAAAABAQEBAQEBAQEBAQEAAAAAAAAAAAAAAAAAAAAAAAAAAAEBAQEBAQEBAQEBAQAAAAAAAAAAAAAAAAAAAAAAAAAAAQEBAQEBAQEBAQEBAAAAAAAAAAAAAAAAAAAAAAAAAAABAQEBAQEBAQEBAQEAAAAAAAAAAAAAAAAAAAAAAAAAAAEBAQEBAQEBAQEBAQAAAAAAAAAAAAAAAAAAAAAAAAAAAQEBAQEBAQEBAQEBAAAAAAAAAAAAAAAAAAAAAAAAAAABAQEBAQEBAQEBAQEAAAAAAAAAAAAAAAAAAAAAAAAAAAEBAQEBAQEBAQEBAQAAAAAAAAAAAAAAAAAAAQEBAQEBAQEBAQEBAQEBAQEBAAAAAAAAAAAAAAAAAAABAQEBAQEBAQEBAQEBAQEBAQEAAAAAAAAAAAAAAAAAAAEBAQEBAQEBAQEBAQEBAQEBAQAAAAAAAAAAAAAAAAAAAQEBAQEBAQEBAQEBAAAAAAAAAAAAAAAAAAAAAAAAAAABAQEBAQEBAQEBAQEAAAAAAAAAAAAAAAAAAAAAAAAAAAEBAQEBAQEBAQEBAQAAAAAAAAAAAAAAAAAAAQEBAQEBAQEBAQEBAQEBAQEBAAAAAAAAAAAAAAAAAAABAQEBAQEBAQEBAQEBAQEBAQEAAAAAAAAAAAAAAAAAAAEBAQEBAQEBAQEBAQEBAQEBAQAAAAAAAAAAAAAAAAAAAQEBAQEBAQEBAQEBAQEBAQEBAAAAAAAAAAAAAAAAAAABAQEBAQEBAQEBAQEBAQEBAQEAAAAAAAAAAAAAAAAAAAEBAQEBAQEBAQEBAQ==" - }, - "palette" : { - "originalArgb8888" : [ -265674 ], - "convertedRgb565" : [ -122 ] } }, "diagnostics" : [ ] @@ -978,14 +978,14 @@ "last_modified" : 1774359772476, "fingerprint" : "eeb7cc665386299403b7be1c272375d5077f3647c587f8033aa8c9275f840562", "metadata" : { + "palette" : { + "originalArgb8888" : [ -265674 ], + "convertedRgb565" : [ -122 ] + }, "tile" : { "width" : 32, "height" : 32, "paletteIndices" : "AQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAAAAAAAAAAABAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEAAAAAAAAAAAEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQAAAAAAAAAAAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAAAAAAAAAAABAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEAAAAAAAAAAAEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQAAAAAAAAAAAQEBAQEBAQEBAQEBAAAAAAAAAAAAAAAAAAAAAAAAAAABAQEBAQEBAQEBAQEAAAAAAAAAAAAAAAAAAAAAAAAAAAEBAQEBAQEBAQEBAQAAAAAAAAAAAAAAAAAAAAAAAAAAAQEBAQEBAQEBAQEBAAAAAAAAAAAAAAAAAAAAAAAAAAABAQEBAQEBAQEBAQEAAAAAAAAAAAAAAAAAAAAAAAAAAAEBAQEBAQEBAQEBAQAAAAAAAAAAAAAAAAAAAAAAAAAAAQEBAQEBAQEBAQEBAAAAAAAAAAAAAAAAAAAAAAAAAAABAQEBAQEBAQEBAQEAAAAAAAAAAAAAAAAAAAAAAAAAAAEBAQEBAQEBAQEBAQAAAAAAAAAAAAAAAAAAAQEBAQEBAQEBAQEBAQEBAQEBAAAAAAAAAAAAAAAAAAABAQEBAQEBAQEBAQEBAQEBAQEAAAAAAAAAAAAAAAAAAAEBAQEBAQEBAQEBAQEBAQEBAQAAAAAAAAAAAAAAAAAAAQEBAQEBAQEBAQEBAAAAAAAAAAAAAAAAAAAAAAAAAAABAQEBAQEBAQEBAQEAAAAAAAAAAAAAAAAAAAAAAAAAAAEBAQEBAQEBAQEBAQAAAAAAAAAAAAAAAAAAAQEBAQEBAQEBAQEBAQEBAQEBAAAAAAAAAAAAAAAAAAABAQEBAQEBAQEBAQEBAQEBAQEAAAAAAAAAAAAAAAAAAAEBAQEBAQEBAQEBAQEBAQEBAQAAAAAAAAAAAAAAAAAAAQEBAQEBAQEBAQEBAQEBAQEBAAAAAAAAAAAAAAAAAAABAQEBAQEBAQEBAQEBAQEBAQEAAAAAAAAAAAAAAAAAAAEBAQEBAQEBAQEBAQ==" - }, - "palette" : { - "originalArgb8888" : [ -265674 ], - "convertedRgb565" : [ -122 ] } }, "diagnostics" : [ ] @@ -996,14 +996,14 @@ "last_modified" : 1774359772478, "fingerprint" : "eeb7cc665386299403b7be1c272375d5077f3647c587f8033aa8c9275f840562", "metadata" : { + "palette" : { + "originalArgb8888" : [ -265674 ], + "convertedRgb565" : [ -122 ] + }, "tile" : { "width" : 32, "height" : 32, "paletteIndices" : "AQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAAAAAAAAAAABAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEAAAAAAAAAAAEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQAAAAAAAAAAAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAAAAAAAAAAABAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEAAAAAAAAAAAEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQAAAAAAAAAAAQEBAQEBAQEBAQEBAAAAAAAAAAAAAAAAAAAAAAAAAAABAQEBAQEBAQEBAQEAAAAAAAAAAAAAAAAAAAAAAAAAAAEBAQEBAQEBAQEBAQAAAAAAAAAAAAAAAAAAAAAAAAAAAQEBAQEBAQEBAQEBAAAAAAAAAAAAAAAAAAAAAAAAAAABAQEBAQEBAQEBAQEAAAAAAAAAAAAAAAAAAAAAAAAAAAEBAQEBAQEBAQEBAQAAAAAAAAAAAAAAAAAAAAAAAAAAAQEBAQEBAQEBAQEBAAAAAAAAAAAAAAAAAAAAAAAAAAABAQEBAQEBAQEBAQEAAAAAAAAAAAAAAAAAAAAAAAAAAAEBAQEBAQEBAQEBAQAAAAAAAAAAAAAAAAAAAQEBAQEBAQEBAQEBAQEBAQEBAAAAAAAAAAAAAAAAAAABAQEBAQEBAQEBAQEBAQEBAQEAAAAAAAAAAAAAAAAAAAEBAQEBAQEBAQEBAQEBAQEBAQAAAAAAAAAAAAAAAAAAAQEBAQEBAQEBAQEBAAAAAAAAAAAAAAAAAAAAAAAAAAABAQEBAQEBAQEBAQEAAAAAAAAAAAAAAAAAAAAAAAAAAAEBAQEBAQEBAQEBAQAAAAAAAAAAAAAAAAAAAQEBAQEBAQEBAQEBAQEBAQEBAAAAAAAAAAAAAAAAAAABAQEBAQEBAQEBAQEBAQEBAQEAAAAAAAAAAAAAAAAAAAEBAQEBAQEBAQEBAQEBAQEBAQAAAAAAAAAAAAAAAAAAAQEBAQEBAQEBAQEBAQEBAQEBAAAAAAAAAAAAAAAAAAABAQEBAQEBAQEBAQEBAQEBAQEAAAAAAAAAAAAAAAAAAAEBAQEBAQEBAQEBAQ==" - }, - "palette" : { - "originalArgb8888" : [ -265674 ], - "convertedRgb565" : [ -122 ] } }, "diagnostics" : [ ] @@ -1014,14 +1014,14 @@ "last_modified" : 1774359772479, "fingerprint" : "eeb7cc665386299403b7be1c272375d5077f3647c587f8033aa8c9275f840562", "metadata" : { + "palette" : { + "originalArgb8888" : [ -265674 ], + "convertedRgb565" : [ -122 ] + }, "tile" : { "width" : 32, "height" : 32, "paletteIndices" : "AQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAAAAAAAAAAABAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEAAAAAAAAAAAEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQAAAAAAAAAAAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAAAAAAAAAAABAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEAAAAAAAAAAAEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQAAAAAAAAAAAQEBAQEBAQEBAQEBAAAAAAAAAAAAAAAAAAAAAAAAAAABAQEBAQEBAQEBAQEAAAAAAAAAAAAAAAAAAAAAAAAAAAEBAQEBAQEBAQEBAQAAAAAAAAAAAAAAAAAAAAAAAAAAAQEBAQEBAQEBAQEBAAAAAAAAAAAAAAAAAAAAAAAAAAABAQEBAQEBAQEBAQEAAAAAAAAAAAAAAAAAAAAAAAAAAAEBAQEBAQEBAQEBAQAAAAAAAAAAAAAAAAAAAAAAAAAAAQEBAQEBAQEBAQEBAAAAAAAAAAAAAAAAAAAAAAAAAAABAQEBAQEBAQEBAQEAAAAAAAAAAAAAAAAAAAAAAAAAAAEBAQEBAQEBAQEBAQAAAAAAAAAAAAAAAAAAAQEBAQEBAQEBAQEBAQEBAQEBAAAAAAAAAAAAAAAAAAABAQEBAQEBAQEBAQEBAQEBAQEAAAAAAAAAAAAAAAAAAAEBAQEBAQEBAQEBAQEBAQEBAQAAAAAAAAAAAAAAAAAAAQEBAQEBAQEBAQEBAAAAAAAAAAAAAAAAAAAAAAAAAAABAQEBAQEBAQEBAQEAAAAAAAAAAAAAAAAAAAAAAAAAAAEBAQEBAQEBAQEBAQAAAAAAAAAAAAAAAAAAAQEBAQEBAQEBAQEBAQEBAQEBAAAAAAAAAAAAAAAAAAABAQEBAQEBAQEBAQEBAQEBAQEAAAAAAAAAAAAAAAAAAAEBAQEBAQEBAQEBAQEBAQEBAQAAAAAAAAAAAAAAAAAAAQEBAQEBAQEBAQEBAQEBAQEBAAAAAAAAAAAAAAAAAAABAQEBAQEBAQEBAQEBAQEBAQEAAAAAAAAAAAAAAAAAAAEBAQEBAQEBAQEBAQ==" - }, - "palette" : { - "originalArgb8888" : [ -265674 ], - "convertedRgb565" : [ -122 ] } }, "diagnostics" : [ ] @@ -1032,14 +1032,14 @@ "last_modified" : 1774359772481, "fingerprint" : "eeb7cc665386299403b7be1c272375d5077f3647c587f8033aa8c9275f840562", "metadata" : { + "palette" : { + "originalArgb8888" : [ -265674 ], + "convertedRgb565" : [ -122 ] + }, "tile" : { "width" : 32, "height" : 32, "paletteIndices" : "AQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAAAAAAAAAAABAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEAAAAAAAAAAAEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQAAAAAAAAAAAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAAAAAAAAAAABAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEAAAAAAAAAAAEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQAAAAAAAAAAAQEBAQEBAQEBAQEBAAAAAAAAAAAAAAAAAAAAAAAAAAABAQEBAQEBAQEBAQEAAAAAAAAAAAAAAAAAAAAAAAAAAAEBAQEBAQEBAQEBAQAAAAAAAAAAAAAAAAAAAAAAAAAAAQEBAQEBAQEBAQEBAAAAAAAAAAAAAAAAAAAAAAAAAAABAQEBAQEBAQEBAQEAAAAAAAAAAAAAAAAAAAAAAAAAAAEBAQEBAQEBAQEBAQAAAAAAAAAAAAAAAAAAAAAAAAAAAQEBAQEBAQEBAQEBAAAAAAAAAAAAAAAAAAAAAAAAAAABAQEBAQEBAQEBAQEAAAAAAAAAAAAAAAAAAAAAAAAAAAEBAQEBAQEBAQEBAQAAAAAAAAAAAAAAAAAAAQEBAQEBAQEBAQEBAQEBAQEBAAAAAAAAAAAAAAAAAAABAQEBAQEBAQEBAQEBAQEBAQEAAAAAAAAAAAAAAAAAAAEBAQEBAQEBAQEBAQEBAQEBAQAAAAAAAAAAAAAAAAAAAQEBAQEBAQEBAQEBAAAAAAAAAAAAAAAAAAAAAAAAAAABAQEBAQEBAQEBAQEAAAAAAAAAAAAAAAAAAAAAAAAAAAEBAQEBAQEBAQEBAQAAAAAAAAAAAAAAAAAAAQEBAQEBAQEBAQEBAQEBAQEBAAAAAAAAAAAAAAAAAAABAQEBAQEBAQEBAQEBAQEBAQEAAAAAAAAAAAAAAAAAAAEBAQEBAQEBAQEBAQEBAQEBAQAAAAAAAAAAAAAAAAAAAQEBAQEBAQEBAQEBAQEBAQEBAAAAAAAAAAAAAAAAAAABAQEBAQEBAQEBAQEBAQEBAQEAAAAAAAAAAAAAAAAAAAEBAQEBAQEBAQEBAQ==" - }, - "palette" : { - "originalArgb8888" : [ -265674 ], - "convertedRgb565" : [ -122 ] } }, "diagnostics" : [ ] @@ -1050,14 +1050,14 @@ "last_modified" : 1774359772482, "fingerprint" : "eeb7cc665386299403b7be1c272375d5077f3647c587f8033aa8c9275f840562", "metadata" : { + "palette" : { + "originalArgb8888" : [ -265674 ], + "convertedRgb565" : [ -122 ] + }, "tile" : { "width" : 32, "height" : 32, "paletteIndices" : "AQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAAAAAAAAAAABAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEAAAAAAAAAAAEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQAAAAAAAAAAAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAAAAAAAAAAABAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEAAAAAAAAAAAEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQAAAAAAAAAAAQEBAQEBAQEBAQEBAAAAAAAAAAAAAAAAAAAAAAAAAAABAQEBAQEBAQEBAQEAAAAAAAAAAAAAAAAAAAAAAAAAAAEBAQEBAQEBAQEBAQAAAAAAAAAAAAAAAAAAAAAAAAAAAQEBAQEBAQEBAQEBAAAAAAAAAAAAAAAAAAAAAAAAAAABAQEBAQEBAQEBAQEAAAAAAAAAAAAAAAAAAAAAAAAAAAEBAQEBAQEBAQEBAQAAAAAAAAAAAAAAAAAAAAAAAAAAAQEBAQEBAQEBAQEBAAAAAAAAAAAAAAAAAAAAAAAAAAABAQEBAQEBAQEBAQEAAAAAAAAAAAAAAAAAAAAAAAAAAAEBAQEBAQEBAQEBAQAAAAAAAAAAAAAAAAAAAQEBAQEBAQEBAQEBAQEBAQEBAAAAAAAAAAAAAAAAAAABAQEBAQEBAQEBAQEBAQEBAQEAAAAAAAAAAAAAAAAAAAEBAQEBAQEBAQEBAQEBAQEBAQAAAAAAAAAAAAAAAAAAAQEBAQEBAQEBAQEBAAAAAAAAAAAAAAAAAAAAAAAAAAABAQEBAQEBAQEBAQEAAAAAAAAAAAAAAAAAAAAAAAAAAAEBAQEBAQEBAQEBAQAAAAAAAAAAAAAAAAAAAQEBAQEBAQEBAQEBAQEBAQEBAAAAAAAAAAAAAAAAAAABAQEBAQEBAQEBAQEBAQEBAQEAAAAAAAAAAAAAAAAAAAEBAQEBAQEBAQEBAQEBAQEBAQAAAAAAAAAAAAAAAAAAAQEBAQEBAQEBAQEBAQEBAQEBAAAAAAAAAAAAAAAAAAABAQEBAQEBAQEBAQEBAQEBAQEAAAAAAAAAAAAAAAAAAAEBAQEBAQEBAQEBAQ==" - }, - "palette" : { - "originalArgb8888" : [ -265674 ], - "convertedRgb565" : [ -122 ] } }, "diagnostics" : [ ] @@ -1068,14 +1068,14 @@ "last_modified" : 1774359772483, "fingerprint" : "eeb7cc665386299403b7be1c272375d5077f3647c587f8033aa8c9275f840562", "metadata" : { + "palette" : { + "originalArgb8888" : [ -265674 ], + "convertedRgb565" : [ -122 ] + }, "tile" : { "width" : 32, "height" : 32, "paletteIndices" : "AQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAAAAAAAAAAABAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEAAAAAAAAAAAEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQAAAAAAAAAAAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAAAAAAAAAAABAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEAAAAAAAAAAAEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQAAAAAAAAAAAQEBAQEBAQEBAQEBAAAAAAAAAAAAAAAAAAAAAAAAAAABAQEBAQEBAQEBAQEAAAAAAAAAAAAAAAAAAAAAAAAAAAEBAQEBAQEBAQEBAQAAAAAAAAAAAAAAAAAAAAAAAAAAAQEBAQEBAQEBAQEBAAAAAAAAAAAAAAAAAAAAAAAAAAABAQEBAQEBAQEBAQEAAAAAAAAAAAAAAAAAAAAAAAAAAAEBAQEBAQEBAQEBAQAAAAAAAAAAAAAAAAAAAAAAAAAAAQEBAQEBAQEBAQEBAAAAAAAAAAAAAAAAAAAAAAAAAAABAQEBAQEBAQEBAQEAAAAAAAAAAAAAAAAAAAAAAAAAAAEBAQEBAQEBAQEBAQAAAAAAAAAAAAAAAAAAAQEBAQEBAQEBAQEBAQEBAQEBAAAAAAAAAAAAAAAAAAABAQEBAQEBAQEBAQEBAQEBAQEAAAAAAAAAAAAAAAAAAAEBAQEBAQEBAQEBAQEBAQEBAQAAAAAAAAAAAAAAAAAAAQEBAQEBAQEBAQEBAAAAAAAAAAAAAAAAAAAAAAAAAAABAQEBAQEBAQEBAQEAAAAAAAAAAAAAAAAAAAAAAAAAAAEBAQEBAQEBAQEBAQAAAAAAAAAAAAAAAAAAAQEBAQEBAQEBAQEBAQEBAQEBAAAAAAAAAAAAAAAAAAABAQEBAQEBAQEBAQEBAQEBAQEAAAAAAAAAAAAAAAAAAAEBAQEBAQEBAQEBAQEBAQEBAQAAAAAAAAAAAAAAAAAAAQEBAQEBAQEBAQEBAQEBAQEBAAAAAAAAAAAAAAAAAAABAQEBAQEBAQEBAQEBAQEBAQEAAAAAAAAAAAAAAAAAAAEBAQEBAQEBAQEBAQ==" - }, - "palette" : { - "originalArgb8888" : [ -265674 ], - "convertedRgb565" : [ -122 ] } }, "diagnostics" : [ ] @@ -1086,14 +1086,14 @@ "last_modified" : 1774359772484, "fingerprint" : "eeb7cc665386299403b7be1c272375d5077f3647c587f8033aa8c9275f840562", "metadata" : { + "palette" : { + "originalArgb8888" : [ -265674 ], + "convertedRgb565" : [ -122 ] + }, "tile" : { "width" : 32, "height" : 32, "paletteIndices" : "AQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAAAAAAAAAAABAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEAAAAAAAAAAAEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQAAAAAAAAAAAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAAAAAAAAAAABAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEAAAAAAAAAAAEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQAAAAAAAAAAAQEBAQEBAQEBAQEBAAAAAAAAAAAAAAAAAAAAAAAAAAABAQEBAQEBAQEBAQEAAAAAAAAAAAAAAAAAAAAAAAAAAAEBAQEBAQEBAQEBAQAAAAAAAAAAAAAAAAAAAAAAAAAAAQEBAQEBAQEBAQEBAAAAAAAAAAAAAAAAAAAAAAAAAAABAQEBAQEBAQEBAQEAAAAAAAAAAAAAAAAAAAAAAAAAAAEBAQEBAQEBAQEBAQAAAAAAAAAAAAAAAAAAAAAAAAAAAQEBAQEBAQEBAQEBAAAAAAAAAAAAAAAAAAAAAAAAAAABAQEBAQEBAQEBAQEAAAAAAAAAAAAAAAAAAAAAAAAAAAEBAQEBAQEBAQEBAQAAAAAAAAAAAAAAAAAAAQEBAQEBAQEBAQEBAQEBAQEBAAAAAAAAAAAAAAAAAAABAQEBAQEBAQEBAQEBAQEBAQEAAAAAAAAAAAAAAAAAAAEBAQEBAQEBAQEBAQEBAQEBAQAAAAAAAAAAAAAAAAAAAQEBAQEBAQEBAQEBAAAAAAAAAAAAAAAAAAAAAAAAAAABAQEBAQEBAQEBAQEAAAAAAAAAAAAAAAAAAAAAAAAAAAEBAQEBAQEBAQEBAQAAAAAAAAAAAAAAAAAAAQEBAQEBAQEBAQEBAQEBAQEBAAAAAAAAAAAAAAAAAAABAQEBAQEBAQEBAQEBAQEBAQEAAAAAAAAAAAAAAAAAAAEBAQEBAQEBAQEBAQEBAQEBAQAAAAAAAAAAAAAAAAAAAQEBAQEBAQEBAQEBAQEBAQEBAAAAAAAAAAAAAAAAAAABAQEBAQEBAQEBAQEBAQEBAQEAAAAAAAAAAAAAAAAAAAEBAQEBAQEBAQEBAQ==" - }, - "palette" : { - "originalArgb8888" : [ -265674 ], - "convertedRgb565" : [ -122 ] } }, "diagnostics" : [ ] @@ -1104,14 +1104,14 @@ "last_modified" : 1774359772485, "fingerprint" : "eeb7cc665386299403b7be1c272375d5077f3647c587f8033aa8c9275f840562", "metadata" : { + "palette" : { + "originalArgb8888" : [ -265674 ], + "convertedRgb565" : [ -122 ] + }, "tile" : { "width" : 32, "height" : 32, "paletteIndices" : "AQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAAAAAAAAAAABAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEAAAAAAAAAAAEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQAAAAAAAAAAAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAAAAAAAAAAABAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEAAAAAAAAAAAEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQAAAAAAAAAAAQEBAQEBAQEBAQEBAAAAAAAAAAAAAAAAAAAAAAAAAAABAQEBAQEBAQEBAQEAAAAAAAAAAAAAAAAAAAAAAAAAAAEBAQEBAQEBAQEBAQAAAAAAAAAAAAAAAAAAAAAAAAAAAQEBAQEBAQEBAQEBAAAAAAAAAAAAAAAAAAAAAAAAAAABAQEBAQEBAQEBAQEAAAAAAAAAAAAAAAAAAAAAAAAAAAEBAQEBAQEBAQEBAQAAAAAAAAAAAAAAAAAAAAAAAAAAAQEBAQEBAQEBAQEBAAAAAAAAAAAAAAAAAAAAAAAAAAABAQEBAQEBAQEBAQEAAAAAAAAAAAAAAAAAAAAAAAAAAAEBAQEBAQEBAQEBAQAAAAAAAAAAAAAAAAAAAQEBAQEBAQEBAQEBAQEBAQEBAAAAAAAAAAAAAAAAAAABAQEBAQEBAQEBAQEBAQEBAQEAAAAAAAAAAAAAAAAAAAEBAQEBAQEBAQEBAQEBAQEBAQAAAAAAAAAAAAAAAAAAAQEBAQEBAQEBAQEBAAAAAAAAAAAAAAAAAAAAAAAAAAABAQEBAQEBAQEBAQEAAAAAAAAAAAAAAAAAAAAAAAAAAAEBAQEBAQEBAQEBAQAAAAAAAAAAAAAAAAAAAQEBAQEBAQEBAQEBAQEBAQEBAAAAAAAAAAAAAAAAAAABAQEBAQEBAQEBAQEBAQEBAQEAAAAAAAAAAAAAAAAAAAEBAQEBAQEBAQEBAQEBAQEBAQAAAAAAAAAAAAAAAAAAAQEBAQEBAQEBAQEBAQEBAQEBAAAAAAAAAAAAAAAAAAABAQEBAQEBAQEBAQEBAQEBAQEAAAAAAAAAAAAAAAAAAAEBAQEBAQEBAQEBAQ==" - }, - "palette" : { - "originalArgb8888" : [ -265674 ], - "convertedRgb565" : [ -122 ] } }, "diagnostics" : [ ] @@ -1122,14 +1122,14 @@ "last_modified" : 1774359772487, "fingerprint" : "eeb7cc665386299403b7be1c272375d5077f3647c587f8033aa8c9275f840562", "metadata" : { + "palette" : { + "originalArgb8888" : [ -265674 ], + "convertedRgb565" : [ -122 ] + }, "tile" : { "width" : 32, "height" : 32, "paletteIndices" : "AQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAAAAAAAAAAABAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEAAAAAAAAAAAEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQAAAAAAAAAAAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAAAAAAAAAAABAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEAAAAAAAAAAAEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQAAAAAAAAAAAQEBAQEBAQEBAQEBAAAAAAAAAAAAAAAAAAAAAAAAAAABAQEBAQEBAQEBAQEAAAAAAAAAAAAAAAAAAAAAAAAAAAEBAQEBAQEBAQEBAQAAAAAAAAAAAAAAAAAAAAAAAAAAAQEBAQEBAQEBAQEBAAAAAAAAAAAAAAAAAAAAAAAAAAABAQEBAQEBAQEBAQEAAAAAAAAAAAAAAAAAAAAAAAAAAAEBAQEBAQEBAQEBAQAAAAAAAAAAAAAAAAAAAAAAAAAAAQEBAQEBAQEBAQEBAAAAAAAAAAAAAAAAAAAAAAAAAAABAQEBAQEBAQEBAQEAAAAAAAAAAAAAAAAAAAAAAAAAAAEBAQEBAQEBAQEBAQAAAAAAAAAAAAAAAAAAAQEBAQEBAQEBAQEBAQEBAQEBAAAAAAAAAAAAAAAAAAABAQEBAQEBAQEBAQEBAQEBAQEAAAAAAAAAAAAAAAAAAAEBAQEBAQEBAQEBAQEBAQEBAQAAAAAAAAAAAAAAAAAAAQEBAQEBAQEBAQEBAAAAAAAAAAAAAAAAAAAAAAAAAAABAQEBAQEBAQEBAQEAAAAAAAAAAAAAAAAAAAAAAAAAAAEBAQEBAQEBAQEBAQAAAAAAAAAAAAAAAAAAAQEBAQEBAQEBAQEBAQEBAQEBAAAAAAAAAAAAAAAAAAABAQEBAQEBAQEBAQEBAQEBAQEAAAAAAAAAAAAAAAAAAAEBAQEBAQEBAQEBAQEBAQEBAQAAAAAAAAAAAAAAAAAAAQEBAQEBAQEBAQEBAQEBAQEBAAAAAAAAAAAAAAAAAAABAQEBAQEBAQEBAQEBAQEBAQEAAAAAAAAAAAAAAAAAAAEBAQEBAQEBAQEBAQ==" - }, - "palette" : { - "originalArgb8888" : [ -265674 ], - "convertedRgb565" : [ -122 ] } }, "diagnostics" : [ ] @@ -1140,14 +1140,14 @@ "last_modified" : 1774359772488, "fingerprint" : "eeb7cc665386299403b7be1c272375d5077f3647c587f8033aa8c9275f840562", "metadata" : { + "palette" : { + "originalArgb8888" : [ -265674 ], + "convertedRgb565" : [ -122 ] + }, "tile" : { "width" : 32, "height" : 32, "paletteIndices" : "AQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAAAAAAAAAAABAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEAAAAAAAAAAAEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQAAAAAAAAAAAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAAAAAAAAAAABAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEAAAAAAAAAAAEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQAAAAAAAAAAAQEBAQEBAQEBAQEBAAAAAAAAAAAAAAAAAAAAAAAAAAABAQEBAQEBAQEBAQEAAAAAAAAAAAAAAAAAAAAAAAAAAAEBAQEBAQEBAQEBAQAAAAAAAAAAAAAAAAAAAAAAAAAAAQEBAQEBAQEBAQEBAAAAAAAAAAAAAAAAAAAAAAAAAAABAQEBAQEBAQEBAQEAAAAAAAAAAAAAAAAAAAAAAAAAAAEBAQEBAQEBAQEBAQAAAAAAAAAAAAAAAAAAAAAAAAAAAQEBAQEBAQEBAQEBAAAAAAAAAAAAAAAAAAAAAAAAAAABAQEBAQEBAQEBAQEAAAAAAAAAAAAAAAAAAAAAAAAAAAEBAQEBAQEBAQEBAQAAAAAAAAAAAAAAAAAAAQEBAQEBAQEBAQEBAQEBAQEBAAAAAAAAAAAAAAAAAAABAQEBAQEBAQEBAQEBAQEBAQEAAAAAAAAAAAAAAAAAAAEBAQEBAQEBAQEBAQEBAQEBAQAAAAAAAAAAAAAAAAAAAQEBAQEBAQEBAQEBAAAAAAAAAAAAAAAAAAAAAAAAAAABAQEBAQEBAQEBAQEAAAAAAAAAAAAAAAAAAAAAAAAAAAEBAQEBAQEBAQEBAQAAAAAAAAAAAAAAAAAAAQEBAQEBAQEBAQEBAQEBAQEBAAAAAAAAAAAAAAAAAAABAQEBAQEBAQEBAQEBAQEBAQEAAAAAAAAAAAAAAAAAAAEBAQEBAQEBAQEBAQEBAQEBAQAAAAAAAAAAAAAAAAAAAQEBAQEBAQEBAQEBAQEBAQEBAAAAAAAAAAAAAAAAAAABAQEBAQEBAQEBAQEBAQEBAQEAAAAAAAAAAAAAAAAAAAEBAQEBAQEBAQEBAQ==" - }, - "palette" : { - "originalArgb8888" : [ -265674 ], - "convertedRgb565" : [ -122 ] } }, "diagnostics" : [ ] @@ -1158,14 +1158,14 @@ "last_modified" : 1774359772489, "fingerprint" : "eeb7cc665386299403b7be1c272375d5077f3647c587f8033aa8c9275f840562", "metadata" : { + "palette" : { + "originalArgb8888" : [ -265674 ], + "convertedRgb565" : [ -122 ] + }, "tile" : { "width" : 32, "height" : 32, "paletteIndices" : "AQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAAAAAAAAAAABAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEAAAAAAAAAAAEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQAAAAAAAAAAAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAAAAAAAAAAABAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEAAAAAAAAAAAEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQAAAAAAAAAAAQEBAQEBAQEBAQEBAAAAAAAAAAAAAAAAAAAAAAAAAAABAQEBAQEBAQEBAQEAAAAAAAAAAAAAAAAAAAAAAAAAAAEBAQEBAQEBAQEBAQAAAAAAAAAAAAAAAAAAAAAAAAAAAQEBAQEBAQEBAQEBAAAAAAAAAAAAAAAAAAAAAAAAAAABAQEBAQEBAQEBAQEAAAAAAAAAAAAAAAAAAAAAAAAAAAEBAQEBAQEBAQEBAQAAAAAAAAAAAAAAAAAAAAAAAAAAAQEBAQEBAQEBAQEBAAAAAAAAAAAAAAAAAAAAAAAAAAABAQEBAQEBAQEBAQEAAAAAAAAAAAAAAAAAAAAAAAAAAAEBAQEBAQEBAQEBAQAAAAAAAAAAAAAAAAAAAQEBAQEBAQEBAQEBAQEBAQEBAAAAAAAAAAAAAAAAAAABAQEBAQEBAQEBAQEBAQEBAQEAAAAAAAAAAAAAAAAAAAEBAQEBAQEBAQEBAQEBAQEBAQAAAAAAAAAAAAAAAAAAAQEBAQEBAQEBAQEBAAAAAAAAAAAAAAAAAAAAAAAAAAABAQEBAQEBAQEBAQEAAAAAAAAAAAAAAAAAAAAAAAAAAAEBAQEBAQEBAQEBAQAAAAAAAAAAAAAAAAAAAQEBAQEBAQEBAQEBAQEBAQEBAAAAAAAAAAAAAAAAAAABAQEBAQEBAQEBAQEBAQEBAQEAAAAAAAAAAAAAAAAAAAEBAQEBAQEBAQEBAQEBAQEBAQAAAAAAAAAAAAAAAAAAAQEBAQEBAQEBAQEBAQEBAQEBAAAAAAAAAAAAAAAAAAABAQEBAQEBAQEBAQEBAQEBAQEAAAAAAAAAAAAAAAAAAAEBAQEBAQEBAQEBAQ==" - }, - "palette" : { - "originalArgb8888" : [ -265674 ], - "convertedRgb565" : [ -122 ] } }, "diagnostics" : [ ] @@ -1176,14 +1176,14 @@ "last_modified" : 1774359772491, "fingerprint" : "eeb7cc665386299403b7be1c272375d5077f3647c587f8033aa8c9275f840562", "metadata" : { + "palette" : { + "originalArgb8888" : [ -265674 ], + "convertedRgb565" : [ -122 ] + }, "tile" : { "width" : 32, "height" : 32, "paletteIndices" : "AQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAAAAAAAAAAABAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEAAAAAAAAAAAEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQAAAAAAAAAAAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAAAAAAAAAAABAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEAAAAAAAAAAAEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQAAAAAAAAAAAQEBAQEBAQEBAQEBAAAAAAAAAAAAAAAAAAAAAAAAAAABAQEBAQEBAQEBAQEAAAAAAAAAAAAAAAAAAAAAAAAAAAEBAQEBAQEBAQEBAQAAAAAAAAAAAAAAAAAAAAAAAAAAAQEBAQEBAQEBAQEBAAAAAAAAAAAAAAAAAAAAAAAAAAABAQEBAQEBAQEBAQEAAAAAAAAAAAAAAAAAAAAAAAAAAAEBAQEBAQEBAQEBAQAAAAAAAAAAAAAAAAAAAAAAAAAAAQEBAQEBAQEBAQEBAAAAAAAAAAAAAAAAAAAAAAAAAAABAQEBAQEBAQEBAQEAAAAAAAAAAAAAAAAAAAAAAAAAAAEBAQEBAQEBAQEBAQAAAAAAAAAAAAAAAAAAAQEBAQEBAQEBAQEBAQEBAQEBAAAAAAAAAAAAAAAAAAABAQEBAQEBAQEBAQEBAQEBAQEAAAAAAAAAAAAAAAAAAAEBAQEBAQEBAQEBAQEBAQEBAQAAAAAAAAAAAAAAAAAAAQEBAQEBAQEBAQEBAAAAAAAAAAAAAAAAAAAAAAAAAAABAQEBAQEBAQEBAQEAAAAAAAAAAAAAAAAAAAAAAAAAAAEBAQEBAQEBAQEBAQAAAAAAAAAAAAAAAAAAAQEBAQEBAQEBAQEBAQEBAQEBAAAAAAAAAAAAAAAAAAABAQEBAQEBAQEBAQEBAQEBAQEAAAAAAAAAAAAAAAAAAAEBAQEBAQEBAQEBAQEBAQEBAQAAAAAAAAAAAAAAAAAAAQEBAQEBAQEBAQEBAQEBAQEBAAAAAAAAAAAAAAAAAAABAQEBAQEBAQEBAQEBAQEBAQEAAAAAAAAAAAAAAAAAAAEBAQEBAQEBAQEBAQ==" - }, - "palette" : { - "originalArgb8888" : [ -265674 ], - "convertedRgb565" : [ -122 ] } }, "diagnostics" : [ ] @@ -1194,14 +1194,14 @@ "last_modified" : 1774359772492, "fingerprint" : "eeb7cc665386299403b7be1c272375d5077f3647c587f8033aa8c9275f840562", "metadata" : { + "palette" : { + "originalArgb8888" : [ -265674 ], + "convertedRgb565" : [ -122 ] + }, "tile" : { "width" : 32, "height" : 32, "paletteIndices" : "AQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAAAAAAAAAAABAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEAAAAAAAAAAAEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQAAAAAAAAAAAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAAAAAAAAAAABAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEAAAAAAAAAAAEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQAAAAAAAAAAAQEBAQEBAQEBAQEBAAAAAAAAAAAAAAAAAAAAAAAAAAABAQEBAQEBAQEBAQEAAAAAAAAAAAAAAAAAAAAAAAAAAAEBAQEBAQEBAQEBAQAAAAAAAAAAAAAAAAAAAAAAAAAAAQEBAQEBAQEBAQEBAAAAAAAAAAAAAAAAAAAAAAAAAAABAQEBAQEBAQEBAQEAAAAAAAAAAAAAAAAAAAAAAAAAAAEBAQEBAQEBAQEBAQAAAAAAAAAAAAAAAAAAAAAAAAAAAQEBAQEBAQEBAQEBAAAAAAAAAAAAAAAAAAAAAAAAAAABAQEBAQEBAQEBAQEAAAAAAAAAAAAAAAAAAAAAAAAAAAEBAQEBAQEBAQEBAQAAAAAAAAAAAAAAAAAAAQEBAQEBAQEBAQEBAQEBAQEBAAAAAAAAAAAAAAAAAAABAQEBAQEBAQEBAQEBAQEBAQEAAAAAAAAAAAAAAAAAAAEBAQEBAQEBAQEBAQEBAQEBAQAAAAAAAAAAAAAAAAAAAQEBAQEBAQEBAQEBAAAAAAAAAAAAAAAAAAAAAAAAAAABAQEBAQEBAQEBAQEAAAAAAAAAAAAAAAAAAAAAAAAAAAEBAQEBAQEBAQEBAQAAAAAAAAAAAAAAAAAAAQEBAQEBAQEBAQEBAQEBAQEBAAAAAAAAAAAAAAAAAAABAQEBAQEBAQEBAQEBAQEBAQEAAAAAAAAAAAAAAAAAAAEBAQEBAQEBAQEBAQEBAQEBAQAAAAAAAAAAAAAAAAAAAQEBAQEBAQEBAQEBAQEBAQEBAAAAAAAAAAAAAAAAAAABAQEBAQEBAQEBAQEBAQEBAQEAAAAAAAAAAAAAAAAAAAEBAQEBAQEBAQEBAQ==" - }, - "palette" : { - "originalArgb8888" : [ -265674 ], - "convertedRgb565" : [ -122 ] } }, "diagnostics" : [ ] @@ -1212,14 +1212,14 @@ "last_modified" : 1774359772493, "fingerprint" : "eeb7cc665386299403b7be1c272375d5077f3647c587f8033aa8c9275f840562", "metadata" : { + "palette" : { + "originalArgb8888" : [ -265674 ], + "convertedRgb565" : [ -122 ] + }, "tile" : { "width" : 32, "height" : 32, "paletteIndices" : "AQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAAAAAAAAAAABAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEAAAAAAAAAAAEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQAAAAAAAAAAAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAAAAAAAAAAABAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEAAAAAAAAAAAEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQAAAAAAAAAAAQEBAQEBAQEBAQEBAAAAAAAAAAAAAAAAAAAAAAAAAAABAQEBAQEBAQEBAQEAAAAAAAAAAAAAAAAAAAAAAAAAAAEBAQEBAQEBAQEBAQAAAAAAAAAAAAAAAAAAAAAAAAAAAQEBAQEBAQEBAQEBAAAAAAAAAAAAAAAAAAAAAAAAAAABAQEBAQEBAQEBAQEAAAAAAAAAAAAAAAAAAAAAAAAAAAEBAQEBAQEBAQEBAQAAAAAAAAAAAAAAAAAAAAAAAAAAAQEBAQEBAQEBAQEBAAAAAAAAAAAAAAAAAAAAAAAAAAABAQEBAQEBAQEBAQEAAAAAAAAAAAAAAAAAAAAAAAAAAAEBAQEBAQEBAQEBAQAAAAAAAAAAAAAAAAAAAQEBAQEBAQEBAQEBAQEBAQEBAAAAAAAAAAAAAAAAAAABAQEBAQEBAQEBAQEBAQEBAQEAAAAAAAAAAAAAAAAAAAEBAQEBAQEBAQEBAQEBAQEBAQAAAAAAAAAAAAAAAAAAAQEBAQEBAQEBAQEBAAAAAAAAAAAAAAAAAAAAAAAAAAABAQEBAQEBAQEBAQEAAAAAAAAAAAAAAAAAAAAAAAAAAAEBAQEBAQEBAQEBAQAAAAAAAAAAAAAAAAAAAQEBAQEBAQEBAQEBAQEBAQEBAAAAAAAAAAAAAAAAAAABAQEBAQEBAQEBAQEBAQEBAQEAAAAAAAAAAAAAAAAAAAEBAQEBAQEBAQEBAQEBAQEBAQAAAAAAAAAAAAAAAAAAAQEBAQEBAQEBAQEBAQEBAQEBAAAAAAAAAAAAAAAAAAABAQEBAQEBAQEBAQEBAQEBAQEAAAAAAAAAAAAAAAAAAAEBAQEBAQEBAQEBAQ==" - }, - "palette" : { - "originalArgb8888" : [ -265674 ], - "convertedRgb565" : [ -122 ] } }, "diagnostics" : [ ] @@ -1230,14 +1230,14 @@ "last_modified" : 1774359772494, "fingerprint" : "eeb7cc665386299403b7be1c272375d5077f3647c587f8033aa8c9275f840562", "metadata" : { + "palette" : { + "originalArgb8888" : [ -265674 ], + "convertedRgb565" : [ -122 ] + }, "tile" : { "width" : 32, "height" : 32, "paletteIndices" : "AQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAAAAAAAAAAABAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEAAAAAAAAAAAEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQAAAAAAAAAAAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAAAAAAAAAAABAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEAAAAAAAAAAAEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQAAAAAAAAAAAQEBAQEBAQEBAQEBAAAAAAAAAAAAAAAAAAAAAAAAAAABAQEBAQEBAQEBAQEAAAAAAAAAAAAAAAAAAAAAAAAAAAEBAQEBAQEBAQEBAQAAAAAAAAAAAAAAAAAAAAAAAAAAAQEBAQEBAQEBAQEBAAAAAAAAAAAAAAAAAAAAAAAAAAABAQEBAQEBAQEBAQEAAAAAAAAAAAAAAAAAAAAAAAAAAAEBAQEBAQEBAQEBAQAAAAAAAAAAAAAAAAAAAAAAAAAAAQEBAQEBAQEBAQEBAAAAAAAAAAAAAAAAAAAAAAAAAAABAQEBAQEBAQEBAQEAAAAAAAAAAAAAAAAAAAAAAAAAAAEBAQEBAQEBAQEBAQAAAAAAAAAAAAAAAAAAAQEBAQEBAQEBAQEBAQEBAQEBAAAAAAAAAAAAAAAAAAABAQEBAQEBAQEBAQEBAQEBAQEAAAAAAAAAAAAAAAAAAAEBAQEBAQEBAQEBAQEBAQEBAQAAAAAAAAAAAAAAAAAAAQEBAQEBAQEBAQEBAAAAAAAAAAAAAAAAAAAAAAAAAAABAQEBAQEBAQEBAQEAAAAAAAAAAAAAAAAAAAAAAAAAAAEBAQEBAQEBAQEBAQAAAAAAAAAAAAAAAAAAAQEBAQEBAQEBAQEBAQEBAQEBAAAAAAAAAAAAAAAAAAABAQEBAQEBAQEBAQEBAQEBAQEAAAAAAAAAAAAAAAAAAAEBAQEBAQEBAQEBAQEBAQEBAQAAAAAAAAAAAAAAAAAAAQEBAQEBAQEBAQEBAQEBAQEBAAAAAAAAAAAAAAAAAAABAQEBAQEBAQEBAQEBAQEBAQEAAAAAAAAAAAAAAAAAAAEBAQEBAQEBAQEBAQ==" - }, - "palette" : { - "originalArgb8888" : [ -265674 ], - "convertedRgb565" : [ -122 ] } }, "diagnostics" : [ ] @@ -1248,14 +1248,14 @@ "last_modified" : 1774359772495, "fingerprint" : "eeb7cc665386299403b7be1c272375d5077f3647c587f8033aa8c9275f840562", "metadata" : { + "palette" : { + "originalArgb8888" : [ -265674 ], + "convertedRgb565" : [ -122 ] + }, "tile" : { "width" : 32, "height" : 32, "paletteIndices" : "AQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAAAAAAAAAAABAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEAAAAAAAAAAAEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQAAAAAAAAAAAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAAAAAAAAAAABAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEAAAAAAAAAAAEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQAAAAAAAAAAAQEBAQEBAQEBAQEBAAAAAAAAAAAAAAAAAAAAAAAAAAABAQEBAQEBAQEBAQEAAAAAAAAAAAAAAAAAAAAAAAAAAAEBAQEBAQEBAQEBAQAAAAAAAAAAAAAAAAAAAAAAAAAAAQEBAQEBAQEBAQEBAAAAAAAAAAAAAAAAAAAAAAAAAAABAQEBAQEBAQEBAQEAAAAAAAAAAAAAAAAAAAAAAAAAAAEBAQEBAQEBAQEBAQAAAAAAAAAAAAAAAAAAAAAAAAAAAQEBAQEBAQEBAQEBAAAAAAAAAAAAAAAAAAAAAAAAAAABAQEBAQEBAQEBAQEAAAAAAAAAAAAAAAAAAAAAAAAAAAEBAQEBAQEBAQEBAQAAAAAAAAAAAAAAAAAAAQEBAQEBAQEBAQEBAQEBAQEBAAAAAAAAAAAAAAAAAAABAQEBAQEBAQEBAQEBAQEBAQEAAAAAAAAAAAAAAAAAAAEBAQEBAQEBAQEBAQEBAQEBAQAAAAAAAAAAAAAAAAAAAQEBAQEBAQEBAQEBAAAAAAAAAAAAAAAAAAAAAAAAAAABAQEBAQEBAQEBAQEAAAAAAAAAAAAAAAAAAAAAAAAAAAEBAQEBAQEBAQEBAQAAAAAAAAAAAAAAAAAAAQEBAQEBAQEBAQEBAQEBAQEBAAAAAAAAAAAAAAAAAAABAQEBAQEBAQEBAQEBAQEBAQEAAAAAAAAAAAAAAAAAAAEBAQEBAQEBAQEBAQEBAQEBAQAAAAAAAAAAAAAAAAAAAQEBAQEBAQEBAQEBAQEBAQEBAAAAAAAAAAAAAAAAAAABAQEBAQEBAQEBAQEBAQEBAQEAAAAAAAAAAAAAAAAAAAEBAQEBAQEBAQEBAQ==" - }, - "palette" : { - "originalArgb8888" : [ -265674 ], - "convertedRgb565" : [ -122 ] } }, "diagnostics" : [ ] @@ -1266,14 +1266,14 @@ "last_modified" : 1775797786950, "fingerprint" : "0526996900bdeef23c72fe987fb45800f11895946dcd5f0f7f8390c879069a37", "metadata" : { + "palette" : { + "originalArgb8888" : [ -265674, -1736296, -13905598, -11518505, -14439577, -2467509 ], + "convertedRgb565" : [ -122, -7149, 11912, 20986, 9548, -9527 ] + }, "tile" : { "width" : 32, "height" : 32, "paletteIndices" : "AQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQECAgIBAQEBAQEBAQEBAQEBAQEBAwMDAwMDAQEBAQEBAgICAgICAgIBAQEBAQEBAQEBAQMDAwMDAwMBAQEBAQICAgICAgICAQEBAQEBAQEBAQEBAQMDAwMDAQEBAQEBAgICAgICAgEBAQEBAQQEBAQBAQEBAQEBAQEBAQEBAQEBAgICAgIBAQEBAQEEBAQEBAQBAQEBAQEBAQEBAQEBAQEBAgECAQEBAQEBAQQEBAQEAQEBAQEBAAAAAAAAAAABAQECAQEBAQEBAQEEBAQEBAEBAQEBAQEAAAAAAAAAAAEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQAAAAAAAAAAAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAAAAAAAAAAABAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEAAAAAAAAAAAEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQAAAAAAAAAAAQEBAQEBAQEBAQEBAAAAAAAAAAAAAAAAAAAAAAAAAAABAQEBAQEBAQEBAQEAAAAAAAAAAAAAAAAAAAAAAAAAAAEBAQEBAQEBAQEBAQAAAAAAAAAAAAAAAAAAAAAAAAAAAQEBAQEBAQUBAQEBAAAAAAAAAAAAAAAAAAAAAAAAAAABAQEBAQUFBQEBAQEAAAAAAAAAAAAAAAAAAAAAAAAAAAEBAQEFBQUFBQEBAQAAAAAAAAAAAAAAAAAAAAAAAAAAAQEBBQUFBQUBAQEBAAAAAAAAAAAAAAAAAAAAAAAAAAABAQEBBQUFAQEBAQEAAAAAAAAAAAAAAAAAAAAAAAAAAAEBAQEBAQEBAQEBAQAAAAAAAAAAAAAAAAAAAQEBAQEBAQEBAQEBAQEBAQEBAAAAAAAAAAAAAAAAAAABAQEBAQEBAQEBAQEBAQEBAQEAAAAAAAAAAAAAAAAAAAEBAQEBAQYGBgYBAQEBAQEBAQAAAAAAAAAAAAAAAAAAAQEBAQEBBgYGBgEBAAAAAAAAAAAAAAAAAAAAAAAAAAABAQEBAQEGBgYGAQEAAAAAAAAAAAAAAAAAAAAAAAAAAAEBAQEBAQYGBgYBAQAAAAAAAAAAAAAAAAAAAQEBAQEBAQEBAQEBAQYGAQEBAAAAAAAAAAAAAAAAAAABAQEBAQEBAQEBAQEBAQEBAQEAAAAAAAAAAAAAAAAAAAEBAQEBAQEBAQEBAQEBAQEBAQAAAAAAAAAAAAAAAAAAAQEBAQEBAQEBAQEBAQEBAQEBAAAAAAAAAAAAAAAAAAABAQEBAQEBAQEBAQEBAQEBAQEAAAAAAAAAAAAAAAAAAAEBAQEBAQEBAQEBAQ==" - }, - "palette" : { - "originalArgb8888" : [ -265674, -1736296, -13905598, -11518505, -14439577, -2467509 ], - "convertedRgb565" : [ -122, -7149, 11912, 20986, 9548, -9527 ] } }, "diagnostics" : [ ] @@ -1314,14 +1314,14 @@ "last_modified" : 1775797786770, "fingerprint" : "aa7d241deabcebe29a6096e14eaf16fdc06cf06380c11a507620b00fc7bff094", "metadata" : { + "palette" : { + "originalArgb8888" : [ -265674 ], + "convertedRgb565" : [ -122 ] + }, "tile" : { "width" : 16, "height" : 16, "paletteIndices" : "AQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAAAAAAEBAQEBAQEBAQEBAQAAAAABAQEBAQEBAQEBAQEAAAAAAQEBAQEBAAAAAAAAAAAAAAEBAQEBAQAAAAAAAAAAAAABAQEBAQEAAAAAAAAAAAAAAQEBAQEBAAAAAAAAAAAAAAEBAQEBAQAAAAAAAAABAQEBAQEBAQEAAAAAAAAAAQEBAQEBAAAAAAAAAAAAAAEBAQEBAQAAAAAAAAABAQEBAQEBAQEAAAAAAAAAAQEBAQEBAQEBAAAAAAAAAAEBAQEBAQ==" - }, - "palette" : { - "originalArgb8888" : [ -265674 ], - "convertedRgb565" : [ -122 ] } }, "diagnostics" : [ ] @@ -1344,14 +1344,14 @@ "last_modified" : 1775797786709, "fingerprint" : "6ca635a7906067b6a2a8460a8562718c445783e6df18b9f2c80c83c5ac569db6", "metadata" : { + "palette" : { + "originalArgb8888" : [ -130562, -14145496, -2043712, -460560, -13082456, -6252424, -10977088 ], + "convertedRgb565" : [ -2017, 10565, -6504, -34, 15125, -23345, 23576 ] + }, "tile" : { "width" : 32, "height" : 32, "paletteIndices" : "AQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQICAgICAgICAgAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAICAwMDAwMDAgAAAAAAAAAAAAACAgIAAAAAAAAAAAAAAAIEBQUFBQUDAgAAAAAAAgICAgMDAwIAAAAAAAAAAAAAAgQFAwYGBgUDAgICAgIDAwMDBQUFAwIAAAAAAAAAAAACBAUDBgYGBgUEBAQEAwUFBQUGAwMFBAICAAAAAAAAAAIEBQMGBgYGAwUFBwcFBgYGBgMDAwMFBAQCAgAAAAAAAgQFAwYGBgMDAwQEBAMGBgYGBgMDAwMHBwQDAgAAAAACBAUDBgYGAwMDAwQEAwYGBgYGAwMDBAQEBQUDAgIAAAIEBQMGBgYDAwMDBAQDBgYGBgYDAwMDBAQDAwUGAgAAAgQFAwYGBgMDAwMEBAMGBgYGBQUFBQUEBAUFBgIAAAACBAUDBgYGAwMDAwQEAwYGBQUGAwMDAwcHAwYCAAAAAAIEBQMFBQUFBQMDBAQDBgUGBgICAgICBAQCAgAAAAAAAgQFBQYGBgYDBQMEBAMFBgICAAAAAAACAgAAAAAAAAACBAMDBgICAgIDBQcHBQYCAAAAAAAAAAAAAAAAAAAAAgIDAwMCAAAAAAIEBAMDAgAAAAAAAAAAAAAAAAAAAAICAgICAgAAAAAAAAICAgIAAAAAAAAAAAAAAAAAAAAAAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQ==" - }, - "palette" : { - "originalArgb8888" : [ -130562, -14145496, -2043712, -460560, -13082456, -6252424, -10977088 ], - "convertedRgb565" : [ -2017, 10565, -6504, -34, 15125, -23345, 23576 ] } }, "diagnostics" : [ { @@ -1396,14 +1396,14 @@ "last_modified" : 1775797786706, "fingerprint" : "7feab8c868bb446afd3dd7250e70504fb0ca228f463650d2dd7c525144e0b321", "metadata" : { + "palette" : { + "originalArgb8888" : [ -16777216, -2109505, -526353, -395279, -130562, -13082456, -10911807, -6318217, -6186631, -6187143, -6318215, -13148249, -13016663, -14080215 ], + "convertedRgb565" : [ 0, -8585, -2115, -66, -2017, 15125, 23544, -25426, -23345, -23377, -25425, 13044, 15125, 10533 ] + }, "tile" : { "width" : 32, "height" : 32, "paletteIndices" : "AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAEBAQEBAQEAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAEBAgMDBAEBAQEBBQUFAAUFBQUFBQUBAQAAAAAAAAAAAAECBgcHBAIICAkBBQUFBQUFBQEBAQICAQEAAAAFBQAAAQIGAwMHBgYGBgIBBQUFBQEBCgIIBgYDBAEBBQUFAAABAgYDAwIJCQsJBgIBAQEBCAgMDA0JAgcHAwMBBQUAAAECBgMDAgsLCwsLBgMDAwIGBgkCCwILAgIHAwEFBQAAAQIGAwMCCQkJCQkCBgcHBgsLCwsCCwICAwMHAwEFAAABAgYDAgkJCQkJCQICAwMCCQkJAgkGBgYHBwcDDgUAAAECBwMCCQkJCQkJAgIDAgkJCQkGBgsCAwMDAwQEAQAAAQIHAwIJCQkJCQkCAgMCCQkJBgkLAQEBAQEBAQQBAAABAgcDAgkJCQkJAgICAwILCQYJAQEFBQUFBQUFAQEAAAECBwMCCQkJCQYGAgIDAgkGCwEFBQUFBQUFBQAAAAAAAQIHAwIJCQYGCQIGBgcMBgkBBQUFBQUFBQAAAAAAAAABAgcGBgYGCQsBAQIDBAIKAQUFBQUFBQAAAAAAAAAAAQECAwIJCQkBAQAAAQEBAQEAAAAAAAAAAAAAAAAAAAEBAQEBAQEBAQAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA==" - }, - "palette" : { - "originalArgb8888" : [ -16777216, -2109505, -526353, -395279, -130562, -13082456, -10911807, -6318217, -6186631, -6187143, -6318215, -13148249, -13016663, -14080215 ], - "convertedRgb565" : [ 0, -8585, -2115, -66, -2017, 15125, 23544, -25426, -23345, -23377, -25425, 13044, 15125, 10533 ] } }, "diagnostics" : [ ] @@ -1414,14 +1414,14 @@ "last_modified" : 1775797786710, "fingerprint" : "c363f3ef7f32d9b249c7dc8babdb3eb5aae68c524099e5e97290202b054dda71", "metadata" : { + "palette" : { + "originalArgb8888" : [ -14671840, -11431408, -9326048, -802016, -3964416, -5086944, -789517, -810399, -1863087, -10403552, -5078447 ], + "convertedRgb565" : [ 8452, 21634, 30084, -2556, -15360, -19708, -2146, -2804, -7030, 25092, -19446 ] + }, "tile" : { "width" : 32, "height" : 32, "paletteIndices" : "AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAABAQEBAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAEBAQICAwMBAQAAAAAAAAAAAAAAAAAAAAAAAAAAAAABBAQBAgIDAwMCAQAAAAAAAAAAAAAAAAAAAAAAAAAAAQUFBAQBAgIDAgICAQAAAAAAAAAAAAAAAAAAAAAAAAABBQEFBAUBAgICAgMBAAAAAAAAAAAAAAAAAAAAAAAAAAABBgEFBQUBAgECAgMBAAAAAAAAAAAAAAAAAAAAAAAAAAEGBwEFBAEBCAECAwEAAAAAAAAAAAAAAAAAAAAAAAAAAQgBBwEEAQgJAQICAQAAAAAAAAAAAAAAAAAAAAAAAAEICAEHAQQBCQYBAgIBAAAAAAAAAAAAAAAAAAAAAAAAAAEGCQkBBQEGAQUBAgEAAAAAAAAAAAAAAAAAAAAAAAAAAAEBBgYBBgEBAQABAAAAAAAAAAAAAAAAAAAAAAAAAAAAAQcBAQEBAgIBAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAECAwECAwIBAgEAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAQECAQcHBwECAQAAAAAAAAAAAAAAAAAAAAAAAAAAAAABBAEBAQEBAQECAQAAAAAAAAAAAAAAAAAAAAAAAAAAAAABAgEJCgoBAgEAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAQEBAQEJCQEBAQAAAAAAAAAAAAAAAAAAAAAAAAAAAAEBAQEKAQEBAQEBAQAAAAAAAAAAAAAAAAAAAAAAAAAAAQEBAQELCwoKAQEBAAAAAAAAAAAAAAAAAAAAAAAAAAAAAQEBAQEBAQEBAQAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAEBAQEBAQAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA==" - }, - "palette" : { - "originalArgb8888" : [ -14671840, -11431408, -9326048, -802016, -3964416, -5086944, -789517, -810399, -1863087, -10403552, -5078447 ], - "convertedRgb565" : [ 8452, 21634, 30084, -2556, -15360, -19708, -2146, -2804, -7030, 25092, -19446 ] } }, "diagnostics" : [ ] @@ -1432,14 +1432,14 @@ "last_modified" : 1775797786711, "fingerprint" : "e2130efbb9643b41a4fb62619f2713402f9622c7db040fe18d929609ef70b89a", "metadata" : { + "palette" : { + "originalArgb8888" : [ -14671840, -11431408, -9326048, -802016, -3964416, -5086944, -789517, -810399, -1863087, -10403552, -5078447 ], + "convertedRgb565" : [ 8452, 21634, 30084, -2556, -15360, -19708, -2146, -2804, -7030, 25092, -19446 ] + }, "tile" : { "width" : 32, "height" : 32, "paletteIndices" : "AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAQEBAQAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAABAQECAgMDAQEAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAQQEAQICAwMDAgEAAAAAAAAAAAAAAAAAAAAAAAAAAAEFBQQEAQICAwICAgEAAAAAAAAAAAAAAAAAAAAAAAAAAQUBBQQFAQICAgIDAQAAAAAAAAAAAAAAAAAAAAAAAAAAAQYBBQUFAQIBAgIDAQAAAAAAAAAAAAAAAAAAAAAAAAABBgcBBQQBAQgBAgMBAAAAAAAAAAAAAAAAAAAAAAAAAAEIAQcBBAEICQECAgEAAAAAAAAAAAAAAAAAAAAAAAABCAgBBwEEAQkGAQICAQAAAAAAAAAAAAAAAAAAAAAAAAABBgkJAQUBBgEFAQIBAAAAAAAAAAAAAAAAAAAAAAAAAAABAQYGAQYBAQEAAQAAAAAAAAAAAAAAAAAAAAAAAAAAAAEHAQEBAQECAQAAAAAAAAAAAAAAAAAAAAAAAAAAAAABAgEBBwMBAwMBAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAEBCQoBBwEDAgEBAAAAAAAAAAAAAAAAAAAAAAAAAAABAgEJCQoBAgIBAQIBAAAAAAAAAAAAAAAAAAAAAAAAAAECAgEBAQICAQECAQEAAAAAAAAAAAAAAAAAAAAAAAAAAAEBAgECAQECAgEBAQAAAAAAAAAAAAAAAAAAAAAAAAAAAQEBAQICAgEBAQoKAQAAAAAAAAAAAAAAAAAAAAAAAAEBAQEBAQEBAQELCwoBAAAAAAAAAAAAAAAAAAAAAAAAAQEBAQEBAQEBAQsLAQEAAAAAAAAAAAAAAAAAAAAAAAAAAQEBAQEBAQEBAQEBAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAEBAQEBAQAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA==" - }, - "palette" : { - "originalArgb8888" : [ -14671840, -11431408, -9326048, -802016, -3964416, -5086944, -789517, -810399, -1863087, -10403552, -5078447 ], - "convertedRgb565" : [ 8452, 21634, 30084, -2556, -15360, -19708, -2146, -2804, -7030, 25092, -19446 ] } }, "diagnostics" : [ ] @@ -1450,14 +1450,14 @@ "last_modified" : 1775797786713, "fingerprint" : "9216dfc6a6226fac398e9f781550d23fbfaa65bd377cdda69187149beca114ec", "metadata" : { + "palette" : { + "originalArgb8888" : [ -14671840, -11431408, -9326048, -802016, -3964416, -5086944, -789517, -810399, -1863087, -10403552, -5078447 ], + "convertedRgb565" : [ 8452, 21634, 30084, -2556, -15360, -19708, -2146, -2804, -7030, 25092, -19446 ] + }, "tile" : { "width" : 32, "height" : 32, "paletteIndices" : "AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAQEBAQAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAEBAQECAgMDAQEAAAEBAAAAAAAAAAAAAAAAAAAAAAABBAQEAQICAwMDAgEBAwEAAAAAAAAAAAAAAAAAAAAAAAEFBQQEAQICAwICAQIDAQAAAAAAAAAAAAAAAAAAAAAAAAEBBQQFAQICAgICAwEBAAAAAAAAAAAAAAAAAAAAAAAAAQYBBQUFAQIBAgICAQAAAAAAAAAAAAAAAAAAAAAAAAABBgcBBQQFAQgBAQEBAAAAAAAAAAAAAAAAAAAAAAAAAAEIAQcBBAUBCQEBBQUBAAAAAAAAAAAAAAAAAAAAAAABCAgBBwgBBAUBAQUBAAAAAAAAAAAAAAAAAAAAAAAAAAABBgkJBgYBAQEBAQAAAAAAAAAAAAAAAAAAAAAAAAAAAAABAQYGBgYBAQAAAAAAAAAAAAAAAAAAAAAAAAAAAAABAQEBAQEBAQMBAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAEJCgEHAwECAwEBAQAAAAAAAAAAAAAAAAAAAAAAAAABAQkKAQcCAQIDAQEBAQAAAAAAAAAAAAAAAAAAAAAAAAEKAQEBAQECAgEBAgELAQAAAAAAAAAAAAAAAAAAAAAAAQEKAQICAQEBAgIBAQoLAQAAAAAAAAAAAAAAAAAAAAAAAQEBAQECAgICAQEAAQEAAAAAAAAAAAAAAAAAAAAAAAAAAQEBAQEBAQEBAQAAAAAAAAAAAAAAAAAAAAAAAAAAAAEBAQEBAQEBAQEBAQAAAAAAAAAAAAAAAAAAAAAAAAAAAQEBAQEBAQEBAQEBAAAAAAAAAAAAAAAAAAAAAAAAAAAAAQEBAQEBAQEBAQAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAEBAQEBAQAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA==" - }, - "palette" : { - "originalArgb8888" : [ -14671840, -11431408, -9326048, -802016, -3964416, -5086944, -789517, -810399, -1863087, -10403552, -5078447 ], - "convertedRgb565" : [ 8452, 21634, 30084, -2556, -15360, -19708, -2146, -2804, -7030, 25092, -19446 ] } }, "diagnostics" : [ ] @@ -1468,14 +1468,14 @@ "last_modified" : 1775797786712, "fingerprint" : "ebc4b7ca7bb1455288681c5d71424f60f658a44cb343d0c3934329cec676c867", "metadata" : { + "palette" : { + "originalArgb8888" : [ -14671840, -11431408, -9326048, -802016, -3964416, -5086944, -789517, -810399, -1863087, -10403552, -5078447 ], + "convertedRgb565" : [ 8452, 21634, 30084, -2556, -15360, -19708, -2146, -2804, -7030, 25092, -19446 ] + }, "tile" : { "width" : 32, "height" : 32, "paletteIndices" : "AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAABAQEBAAAAAAEBAAAAAAAAAAAAAAAAAAAAAAAAAAEBAQICAwMBAQEBAwEAAAAAAAAAAAAAAAAAAAAAAAABBAQBAgIDAwMCAQMDAQAAAAAAAAAAAAAAAAAAAAAAAQUFBAQBAgIDAgICAwIBAAAAAAAAAAAAAAAAAAAAAAABBQEFBAUBAgICAgMCAQAAAAAAAAAAAAAAAAAAAAAAAAABBgEFBQUBAgECAgIBAAAAAAAAAAAAAAAAAAAAAAAAAAEGBwEFBAUBCAEBAQAAAAAAAAAAAAAAAAAAAAAAAAAAAQgBBwEEBQEJAQEAAAAAAAAAAAAAAAAAAAAAAAAAAAEICAEHCQEEBQEFAQAAAAAAAAAAAAAAAAAAAAAAAAAAAQEBCQkGBgEBAQUBAAAAAAAAAAAAAAAAAAAAAAAAAAABCQoBAQEGBgEBAQUBAAAAAAAAAAAAAAAAAAAAAAAAAAEKCgEHAgEBAQMBAQAAAAAAAAAAAAAAAAAAAAAAAAAAAAEBBwICAQIDAwEBAAAAAAAAAAAAAAAAAAAAAAAAAAABAQEBAQECAgMBAQIBAAAAAAAAAAAAAAAAAAAAAAAAAQoBAQIBAgICAgECAQEAAAAAAAAAAAAAAAAAAAAAAAABCgoBAgIBAQEBAgELAQAAAAAAAAAAAAAAAAAAAAAAAAEBAQEBAQICAgIBAQEAAAAAAAAAAAAAAAAAAAAAAAAAAAEBAQEBAQEBAQEBAQAAAAAAAAAAAAAAAAAAAAAAAAAAAQEBAQEBAQEBAQEBAAAAAAAAAAAAAAAAAAAAAAAAAAAAAQEBAQEBAQEBAQAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAEBAQEBAQAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA==" - }, - "palette" : { - "originalArgb8888" : [ -14671840, -11431408, -9326048, -802016, -3964416, -5086944, -789517, -810399, -1863087, -10403552, -5078447 ], - "convertedRgb565" : [ 8452, 21634, 30084, -2556, -15360, -19708, -2146, -2804, -7030, 25092, -19446 ] } }, "diagnostics" : [ ] @@ -1486,14 +1486,14 @@ "last_modified" : 1775797786718, "fingerprint" : "c363f3ef7f32d9b249c7dc8babdb3eb5aae68c524099e5e97290202b054dda71", "metadata" : { + "palette" : { + "originalArgb8888" : [ -14671840, -11431408, -9326048, -802016, -3964416, -5086944, -789517, -810399, -1863087, -10403552, -5078447 ], + "convertedRgb565" : [ 8452, 21634, 30084, -2556, -15360, -19708, -2146, -2804, -7030, 25092, -19446 ] + }, "tile" : { "width" : 32, "height" : 32, "paletteIndices" : "AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAABAQEBAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAEBAQICAwMBAQAAAAAAAAAAAAAAAAAAAAAAAAAAAAABBAQBAgIDAwMCAQAAAAAAAAAAAAAAAAAAAAAAAAAAAQUFBAQBAgIDAgICAQAAAAAAAAAAAAAAAAAAAAAAAAABBQEFBAUBAgICAgMBAAAAAAAAAAAAAAAAAAAAAAAAAAABBgEFBQUBAgECAgMBAAAAAAAAAAAAAAAAAAAAAAAAAAEGBwEFBAEBCAECAwEAAAAAAAAAAAAAAAAAAAAAAAAAAQgBBwEEAQgJAQICAQAAAAAAAAAAAAAAAAAAAAAAAAEICAEHAQQBCQYBAgIBAAAAAAAAAAAAAAAAAAAAAAAAAAEGCQkBBQEGAQUBAgEAAAAAAAAAAAAAAAAAAAAAAAAAAAEBBgYBBgEBAQABAAAAAAAAAAAAAAAAAAAAAAAAAAAAAQcBAQEBAgIBAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAECAwECAwIBAgEAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAQECAQcHBwECAQAAAAAAAAAAAAAAAAAAAAAAAAAAAAABBAEBAQEBAQECAQAAAAAAAAAAAAAAAAAAAAAAAAAAAAABAgEJCgoBAgEAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAQEBAQEJCQEBAQAAAAAAAAAAAAAAAAAAAAAAAAAAAAEBAQEKAQEBAQEBAQAAAAAAAAAAAAAAAAAAAAAAAAAAAQEBAQELCwoKAQEBAAAAAAAAAAAAAAAAAAAAAAAAAAAAAQEBAQEBAQEBAQAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAEBAQEBAQAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA==" - }, - "palette" : { - "originalArgb8888" : [ -14671840, -11431408, -9326048, -802016, -3964416, -5086944, -789517, -810399, -1863087, -10403552, -5078447 ], - "convertedRgb565" : [ 8452, 21634, 30084, -2556, -15360, -19708, -2146, -2804, -7030, 25092, -19446 ] } }, "diagnostics" : [ ] @@ -1504,14 +1504,14 @@ "last_modified" : 1775797786717, "fingerprint" : "1ba8ce75c445396334737143e0cfa56c87a1fb64cca8ad0962192594849249eb", "metadata" : { + "palette" : { + "originalArgb8888" : [ -14671840, -11431408, -9326048, -802016, -3964416, -5086944, -789517, -810399, -1863087, -10403552 ], + "convertedRgb565" : [ 8452, 21634, 30084, -2556, -15360, -19708, -2146, -2804, -7030, 25092 ] + }, "tile" : { "width" : 32, "height" : 32, "paletteIndices" : "AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAABAQEBAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAEBAQICAwMBAQAAAAAAAAAAAAAAAAAAAAAAAAAAAAABBAQBAgIDAwMCAQAAAAAAAAAAAAAAAAAAAAAAAAAAAQUFBAQBAgIDAgICAQAAAAAAAAAAAAAAAAAAAAAAAAABBQEFBAUBAgICAgMBAAAAAAAAAAAAAAAAAAAAAAAAAAABBgEFBQUBAgECAgMBAAAAAAAAAAAAAAAAAAAAAAAAAAEGBwEFBAEBCAECAwEAAAAAAAAAAAAAAAAAAAAAAAAAAQgBBwEEAQgJAQICAQAAAAAAAAAAAAAAAAAAAAAAAAEICAEHAQQBCQYBAgIBAAAAAAAAAAAAAAAAAAAAAAAAAAEGCQkBBQEGAQUBAgEAAAAAAAAAAAAAAAAAAAAAAAAAAAEBBgYBAQEBAQABAAAAAAAAAAAAAAAAAAAAAAAAAAAAAQcBAQEDAQEAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAABAwMBAgcHAQAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAQMDAwIBAQEBAQAAAAAAAAAAAAAAAAAAAAAAAAAAAAABBAIDAgEKCgECAQAAAAAAAAAAAAAAAAAAAAAAAAAAAAECAQEBAQkJAQIBAAAAAAAAAAAAAAAAAAAAAAAAAAAAAQECAgICAQECAQoBAAAAAAAAAAAAAAAAAAAAAAAAAAABAQEBAQICAgEKCgEAAAAAAAAAAAAAAAAAAAAAAAAAAQEBAQEBAQEBCgoKAQAAAAAAAAAAAAAAAAAAAAAAAAABAQEBAQEBAQEBAQEAAAAAAAAAAAAAAAAAAAAAAAAAAAABAQEBAQEBAQEBAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAQEBAQEBAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA==" - }, - "palette" : { - "originalArgb8888" : [ -14671840, -11431408, -9326048, -802016, -3964416, -5086944, -789517, -810399, -1863087, -10403552 ], - "convertedRgb565" : [ 8452, 21634, 30084, -2556, -15360, -19708, -2146, -2804, -7030, 25092 ] } }, "diagnostics" : [ ] @@ -1522,14 +1522,14 @@ "last_modified" : 1775797786714, "fingerprint" : "5e0954447699c6d5eac7550f1a10cf520efcddad0b9fbd9a716434da9d9550d4", "metadata" : { + "palette" : { + "originalArgb8888" : [ -14671840, -11431408, -9326048, -802016, -3964416, -5086944, -789517, -810399, -1863087, -10403552, -5078447 ], + "convertedRgb565" : [ 8452, 21634, 30084, -2556, -15360, -19708, -2146, -2804, -7030, 25092, -19446 ] + }, "tile" : { "width" : 32, "height" : 32, "paletteIndices" : "AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAABAQEBAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAQEBAQICAwMBAQAAAAAAAAAAAAAAAAAAAAAAAAAAAAEEBAQBAgIDAwMCAQABAQAAAAAAAAAAAAAAAAAAAAAAAQUFBAQBAgIDAgIBAQMBAAAAAAAAAAAAAAAAAAAAAAAAAQEFBAUBAgICAgIDAwEAAAAAAAAAAAAAAAAAAAAAAAABBgEFBQUBAgECAgIBAAAAAAAAAAAAAAAAAAAAAAAAAAEGBwEFBAUBCAEBAQEAAAAAAAAAAAAAAAAAAAAAAAAAAQgBBwEEBQEJAQEFBQEAAAAAAAAAAAAAAAAAAAAAAAEICAEHCAEEBQEBBQEBAAAAAAAAAAAAAAAAAAAAAAAAAAEGCQkGBgEBAQEBAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAEBBgYGAQIDAQAAAAAAAAAAAAAAAAAAAAAAAAAAAAABCQEBAQEBAQEHAQAAAAAAAAAAAAAAAAAAAAAAAAAAAQEBBwcDAgEKCgEBAAAAAAAAAAAAAAAAAAAAAAAAAAABAgIBAwMCAQkJAQEAAAAAAAAAAAAAAAAAAAAAAAAAAQEBAQIBAgMCAQEBCgEAAAAAAAAAAAAAAAAAAAAAAAABCwsKAQIBAQECAgEKAQAAAAAAAAAAAAAAAAAAAAAAAAABCwsKAQICAgIBCgoBAAAAAAAAAAAAAAAAAAAAAAAAAAABAQEBAQEBAQEBAQAAAAAAAAAAAAAAAAAAAAAAAAAAAQEBAQEBAQEBAQEBAAAAAAAAAAAAAAAAAAAAAAAAAAABAQEBAQEBAQEBAQEAAAAAAAAAAAAAAAAAAAAAAAAAAAABAQEBAQEBAQEBAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAQEBAQEBAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA==" - }, - "palette" : { - "originalArgb8888" : [ -14671840, -11431408, -9326048, -802016, -3964416, -5086944, -789517, -810399, -1863087, -10403552, -5078447 ], - "convertedRgb565" : [ 8452, 21634, 30084, -2556, -15360, -19708, -2146, -2804, -7030, 25092, -19446 ] } }, "diagnostics" : [ ] @@ -1540,14 +1540,14 @@ "last_modified" : 1775797786716, "fingerprint" : "6104ba7f216a937994d478ed07766ec28f48ad72fdd6620508535a1f877b8ddb", "metadata" : { + "palette" : { + "originalArgb8888" : [ -14671840, -11431408, -9326048, -802016, -3964416, -5086944, -789517, -810399, -1863087, -10403552, -5078447 ], + "convertedRgb565" : [ 8452, 21634, 30084, -2556, -15360, -19708, -2146, -2804, -7030, 25092, -19446 ] + }, "tile" : { "width" : 32, "height" : 32, "paletteIndices" : "AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAABAQEBAAAAAAEBAAAAAAAAAAAAAAAAAAAAAAAAAAEBAQICAwMBAQEBAwEAAAAAAAAAAAAAAAAAAAAAAAABBAQBAgIDAwMCAQMDAQAAAAAAAAAAAAAAAAAAAAAAAQUFBAQBAgIDAgICAwIBAAAAAAAAAAAAAAAAAAAAAAABBQEFBAUBAgICAgMCAQAAAAAAAAAAAAAAAAAAAAAAAAABBgEFBQUBAgECAgIBAAAAAAAAAAAAAAAAAAAAAAAAAAEGBwEFBAUBCAEBAQAAAAAAAAAAAAAAAAAAAAAAAAAAAQgBBwEEBQEJAQEAAAAAAAAAAAAAAAAAAAAAAAAAAAEICAEHCQEEBQEFAQAAAAAAAAAAAAAAAAAAAAAAAAAAAAEGCQkGBgEBAQEBAAAAAAAAAAAAAAAAAAAAAAAAAAABAQEBBgYGAQIDAgEBAAAAAAAAAAAAAAAAAAAAAAAAAAEJAQEBAQEBAgIBAQAAAAAAAAAAAAAAAAAAAAAAAAAAAAEBBwcDAgIBAQoKAQAAAAAAAAAAAAAAAAAAAAAAAAAAAQQBAwMDAgIBCQkBAAAAAAAAAAAAAAAAAAAAAAAAAAEBAgECAwMCAQEBAQEAAAAAAAAAAAAAAAAAAAAAAAABCwYBAgEBAQECAgEKAQAAAAAAAAAAAAAAAAAAAAAAAAELCgYBAgICAgEBAQEAAAAAAAAAAAAAAAAAAAAAAAAAAAEKCgoBAQEBAQEBAQAAAAAAAAAAAAAAAAAAAAAAAAAAAQEBAQEBAQEBAQEBAAAAAAAAAAAAAAAAAAAAAAAAAAAAAQEBAQEBAQEBAQAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAEBAQEBAQAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA==" - }, - "palette" : { - "originalArgb8888" : [ -14671840, -11431408, -9326048, -802016, -3964416, -5086944, -789517, -810399, -1863087, -10403552, -5078447 ], - "convertedRgb565" : [ 8452, 21634, 30084, -2556, -15360, -19708, -2146, -2804, -7030, 25092, -19446 ] } }, "diagnostics" : [ ] @@ -1602,14 +1602,14 @@ "last_modified" : 1776965154257, "fingerprint" : "8771c3e294d0edbc8dd3aaa6995a6db32166ae6bfb3e063170cc79b298d17e71", "metadata" : { + "palette" : { + "originalArgb8888" : [ -12019640 ], + "convertedRgb565" : [ 19657 ] + }, "tile" : { "width" : 8, "height" : 8, "paletteIndices" : "AQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQ==" - }, - "palette" : { - "originalArgb8888" : [ -12019640 ], - "convertedRgb565" : [ 19657 ] } }, "diagnostics" : [ ] @@ -1620,14 +1620,14 @@ "last_modified" : 1776965154257, "fingerprint" : "5d81eef8be13043330b42b546e10beed8ba00dfaa42df67477a8778c2b9484d7", "metadata" : { + "palette" : { + "originalArgb8888" : [ -12019640, -12552128, -14129088, -14133200, -14145496, -7835584, -5730208, -10465232 ], + "convertedRgb565" : [ 19657, 17352, 11080, 10950, 10565, -29816, -21364, 25222 ] + }, "tile" : { "width" : 8, "height" : 8, "paletteIndices" : "AQEBAQEBAQEBAQEBAQICAgECAgICAgICAgMEBQUFBQQDBAUGBgYGBQMEBQYGBwcIAwQFCAYGCAgBAwUFCAgIBw==" - }, - "palette" : { - "originalArgb8888" : [ -12019640, -12552128, -14129088, -14133200, -14145496, -7835584, -5730208, -10465232 ], - "convertedRgb565" : [ 19657, 17352, 11080, 10950, 10565, -29816, -21364, 25222 ] } }, "diagnostics" : [ ] @@ -1638,14 +1638,14 @@ "last_modified" : 1776965154258, "fingerprint" : "3250840c4fe08c134ea966ce7c8fcaccae2c2a45660d7173c5e262a2e5076548", "metadata" : { + "palette" : { + "originalArgb8888" : [ -12552128, -14133200, -14145496, -10465232, -5730208, -7835584 ], + "convertedRgb565" : [ 17352, 10950, 10565, 25222, -21364, -29816 ] + }, "tile" : { "width" : 8, "height" : 8, "paletteIndices" : "AQEBAQECAwMBAQEBAgMEBQEBAQIDBAUFAQIDAwQEBAQDAwYFBQUFBQQGBQUGBgYGBQUFBgYFBQUFBgYGBQUGBg==" - }, - "palette" : { - "originalArgb8888" : [ -12552128, -14133200, -14145496, -10465232, -5730208, -7835584 ], - "convertedRgb565" : [ 17352, 10950, 10565, 25222, -21364, -29816 ] } }, "diagnostics" : [ ] @@ -1656,14 +1656,14 @@ "last_modified" : 1776965154258, "fingerprint" : "fe3ab2b7eb3b10a042de14484d53e718e6b505edb1ad19053668565bfe3a8f25", "metadata" : { + "palette" : { + "originalArgb8888" : [ -14145496, -14133200, -12552128, -5730208, -10465232, -7835584 ], + "convertedRgb565" : [ 10565, 10950, 17352, -21364, 25222, -29816 ] + }, "tile" : { "width" : 8, "height" : 8, "paletteIndices" : "AQECAwMDAwMEBQECAwMDAwQEBQECAwMDBQUFBQEBAgMEBAQEBAYBAQYGBgYEBAYFBAQEBgYEBAQGBgQEBgYGBA==" - }, - "palette" : { - "originalArgb8888" : [ -14145496, -14133200, -12552128, -5730208, -10465232, -7835584 ], - "convertedRgb565" : [ 10565, 10950, 17352, -21364, 25222, -29816 ] } }, "diagnostics" : [ ] @@ -1674,14 +1674,14 @@ "last_modified" : 1776965154259, "fingerprint" : "7fcbf90e1e9a69d6ce3be80ea1901d66c9992f68dc72e4c636dcd2ad52fa2898", "metadata" : { + "palette" : { + "originalArgb8888" : [ -12019640, -12552128, -14133200, -14145496, -14129088, -7835584, -10465232, -5730208 ], + "convertedRgb565" : [ 19657, 17352, 10950, 10565, 11080, -29816, 25222, -21364 ] + }, "tile" : { "width" : 8, "height" : 8, "paletteIndices" : "AQEBAQEBAQECAgIBAQEBAQICAgICAgIBAwQEBAQDBQIEBgYGBgQDBQcICAYGBAMFBwcGBgcEAwUIBwcHBAQFAQ==" - }, - "palette" : { - "originalArgb8888" : [ -12019640, -12552128, -14133200, -14145496, -14129088, -7835584, -10465232, -5730208 ], - "convertedRgb565" : [ 19657, 17352, 10950, 10565, 11080, -29816, 25222, -21364 ] } }, "diagnostics" : [ ] @@ -1692,14 +1692,14 @@ "last_modified" : 1776965154259, "fingerprint" : "451fc8d646049944d5aa7c7dc254636eec0151aaff6e2051059304b9d6ebc31e", "metadata" : { + "palette" : { + "originalArgb8888" : [ -12019640, -14129088, -14133200, -14145496, -10465232, -5730208, -7835584 ], + "convertedRgb565" : [ 19657, 11080, 10950, 10565, 25222, -21364, -29816 ] + }, "tile" : { "width" : 8, "height" : 8, "paletteIndices" : "AQIDBAQFBgYBAQIDBAYGBwEBAQMEBgcHAQEBBAQGBwcBAQQFBAYHBwEEBwUEBgcHBAcGBQQGBwcEBwYFBAYHBw==" - }, - "palette" : { - "originalArgb8888" : [ -12019640, -14129088, -14133200, -14145496, -10465232, -5730208, -7835584 ], - "convertedRgb565" : [ 19657, 11080, 10950, 10565, 25222, -21364, -29816 ] } }, "diagnostics" : [ ] @@ -1710,14 +1710,14 @@ "last_modified" : 1776965154260, "fingerprint" : "aa757df4600823ec6655235a1081061777124ccee74b31481bbe402e53635f53", "metadata" : { + "palette" : { + "originalArgb8888" : [ -7835584, -5730208, -10465232, -14145496 ], + "convertedRgb565" : [ -29816, -21364, 25222, 10565 ] + }, "tile" : { "width" : 8, "height" : 8, "paletteIndices" : "AQECAwMBAQEBAgIBAwMBAgICAQEBAwMCAgIBAQIDBAMCAgEBAgMEBAICAQECAwQEAgIBAQIDBAMCAgIBAwQDAg==" - }, - "palette" : { - "originalArgb8888" : [ -7835584, -5730208, -10465232, -14145496 ], - "convertedRgb565" : [ -29816, -21364, 25222, 10565 ] } }, "diagnostics" : [ ] @@ -1728,14 +1728,14 @@ "last_modified" : 1776965154260, "fingerprint" : "38162157f5685cce25b835d3a2caee3465fd2ec3ee5db2a5089d7d5ae5ea3bb7", "metadata" : { + "palette" : { + "originalArgb8888" : [ -7835584, -10465232, -5730208, -14145496 ], + "convertedRgb565" : [ -29816, 25222, -21364, 10565 ] + }, "tile" : { "width" : 8, "height" : 8, "paletteIndices" : "AQEBAgIDAQEDAQICAQMDAQMCAgEBAQMDAgQCAwEBAwMEBAIDAQEDAwQEAgMBAQMDAgQCAwEBAwMDAgQCAQMDAw==" - }, - "palette" : { - "originalArgb8888" : [ -7835584, -10465232, -5730208, -14145496 ], - "convertedRgb565" : [ -29816, 25222, -21364, 10565 ] } }, "diagnostics" : [ ] @@ -1746,14 +1746,14 @@ "last_modified" : 1776965154260, "fingerprint" : "8cab5b3d553af9ed371bd19fc624763accc90e5d926d300ba31dd8d9d6bab803", "metadata" : { + "palette" : { + "originalArgb8888" : [ -5730208, -10465232, -14145496, -14133200, -14129088, -12019640, -7835584 ], + "convertedRgb565" : [ -21364, 25222, 10565, 10950, 11080, 19657, -29816 ] + }, "tile" : { "width" : 8, "height" : 8, "paletteIndices" : "AQECAwMEBQYHAQEDBAUGBgcHAQMEBgYGBwcBAwMGBgYHBwEDAgMGBgcHAQMCBwMGBwcBAwIBBwMHBwEDAgEHAw==" - }, - "palette" : { - "originalArgb8888" : [ -5730208, -10465232, -14145496, -14133200, -14129088, -12019640, -7835584 ], - "convertedRgb565" : [ -21364, 25222, 10565, 10950, 11080, 19657, -29816 ] } }, "diagnostics" : [ ] @@ -1764,14 +1764,14 @@ "last_modified" : 1776965154261, "fingerprint" : "d9ff5a6df0f65f5fcfb8f22376beeb266d429e2c6e9c82f51c12bc6ee4c3fcdc", "metadata" : { + "palette" : { + "originalArgb8888" : [ -14145496, -10465232, -7835584, -5730208, -14133200, -14129088, -12019640 ], + "convertedRgb565" : [ 10565, 25222, -29816, -21364, 10950, 11080, 19657 ] + }, "tile" : { "width" : 8, "height" : 8, "paletteIndices" : "AQIDAgIBBAMFAQECAgEEBAUGBQECAgEEBwYFBQECAQEHBwYGBQEBAgcHBwYFAQMDBwcHBwEBAwMHBwcFAQICAw==" - }, - "palette" : { - "originalArgb8888" : [ -14145496, -10465232, -7835584, -5730208, -14133200, -14129088, -12019640 ], - "convertedRgb565" : [ 10565, 25222, -29816, -21364, 10950, 11080, 19657 ] } }, "diagnostics" : [ ] @@ -1782,14 +1782,14 @@ "last_modified" : 1776965154261, "fingerprint" : "b9ff45c77f7779a6acebcc537c2ddac0e27e91162b656a04dc4772ec5f24fc26", "metadata" : { + "palette" : { + "originalArgb8888" : [ -7835584, -5730208, -10465232, -14145496 ], + "convertedRgb565" : [ -29816, -21364, 25222, 10565 ] + }, "tile" : { "width" : 8, "height" : 8, "paletteIndices" : "AQICAwMBAQIBAQMDAgIBAQIBAQEBAgIBAgICAgEBAgIEAwMCAgEBAQMEAwMCAgEBAQMEAwMDAgIBAwMEAwMDAw==" - }, - "palette" : { - "originalArgb8888" : [ -7835584, -5730208, -10465232, -14145496 ], - "convertedRgb565" : [ -29816, -21364, 25222, 10565 ] } }, "diagnostics" : [ ] @@ -1800,14 +1800,14 @@ "last_modified" : 1776965154261, "fingerprint" : "43f370324fedccda888d49409e2a64f182f08b4143b4bdd5bafaf498feebd21a", "metadata" : { + "palette" : { + "originalArgb8888" : [ -5730208, -7835584, -10465232, -14145496 ], + "convertedRgb565" : [ -21364, -29816, 25222, 10565 ] + }, "tile" : { "width" : 8, "height" : 8, "paletteIndices" : "AQICAwMBAQICAgEBAwMCAgIBAQICAgIBAQECAgEBAQECAgIBAQMDBAICAQEDAwQDAQEDAwMEAwIDAwMDBAMDAg==" - }, - "palette" : { - "originalArgb8888" : [ -5730208, -7835584, -10465232, -14145496 ], - "convertedRgb565" : [ -21364, -29816, 25222, 10565 ] } }, "diagnostics" : [ ] @@ -1818,14 +1818,14 @@ "last_modified" : 1776965154262, "fingerprint" : "cb047e655f4e196f22ca0048149df5dcb959f895faeaeb94920182d4a2d16b38", "metadata" : { + "palette" : { + "originalArgb8888" : [ -7835584, -5730208, -14145496, -10465232, -14133200, -14129088, -12019640 ], + "convertedRgb565" : [ -29816, -21364, 10565, 25222, 10950, 11080, 19657 ] + }, "tile" : { "width" : 8, "height" : 8, "paletteIndices" : "AQIDBAQBBAMCAgMEBAMDBQIDBAQDBQYFAwMEAwUFBgcEAwMFBgYHBwEBAwUGBwcHAQEDAwcHBwcBBAQDBQcHBw==" - }, - "palette" : { - "originalArgb8888" : [ -7835584, -5730208, -14145496, -10465232, -14133200, -14129088, -12019640 ], - "convertedRgb565" : [ -29816, -21364, 10565, 25222, 10950, 11080, 19657 ] } }, "diagnostics" : [ ] @@ -1836,14 +1836,14 @@ "last_modified" : 1776965154262, "fingerprint" : "25eba17b67dd5159f5fb9d3edd531d54a44d1c76f997385840dac53517b98886", "metadata" : { + "palette" : { + "originalArgb8888" : [ -12019640, -14145496, -7835584, -10465232, -14133200, -14129088 ], + "convertedRgb565" : [ 19657, 10565, -29816, 25222, 10950, 11080 ] + }, "tile" : { "width" : 8, "height" : 8, "paletteIndices" : "AQEBAgMDBAQBAQIDAwMDBAEBAgMDAwMEAQECAwMEAgQBAQIEAgUFAgEBBQUGBQYFAQEBAQEGAQYBAQEBAQEBAQ==" - }, - "palette" : { - "originalArgb8888" : [ -12019640, -14145496, -7835584, -10465232, -14133200, -14129088 ], - "convertedRgb565" : [ 19657, 10565, -29816, 25222, 10950, 11080 ] } }, "diagnostics" : [ ] @@ -1854,14 +1854,14 @@ "last_modified" : 1776965154262, "fingerprint" : "32ca96c14290de8009fd2db623f55514bed2345b7d5881a80dd3fe6235012854", "metadata" : { + "palette" : { + "originalArgb8888" : [ -10465232, -14145496, -14133200, -7835584, -14129088, -12019640 ], + "convertedRgb565" : [ 25222, 10565, 10950, -29816, 11080, 19657 ] + }, "tile" : { "width" : 8, "height" : 8, "paletteIndices" : "AQEBAgEBAgICAQICAQIBAQICAwICAQEEAgMDAwIBAQQDAwUDAwIBAQUFBgUFAgEEBgYGBgYDAgEGBgYGBgYDAg==" - }, - "palette" : { - "originalArgb8888" : [ -10465232, -14145496, -14133200, -7835584, -14129088, -12019640 ], - "convertedRgb565" : [ 25222, 10565, 10950, -29816, 11080, 19657 ] } }, "diagnostics" : [ ] @@ -1872,14 +1872,14 @@ "last_modified" : 1776965154263, "fingerprint" : "7a093fe00c805bcf38d4facff14a6d4c2b8baeaa2d553fa8d3db9f2d76b32f3b", "metadata" : { + "palette" : { + "originalArgb8888" : [ -14145496, -10465232, -7835584, -14133200, -14129088, -12019640 ], + "convertedRgb565" : [ 10565, 25222, -29816, 10950, 11080, 19657 ] + }, "tile" : { "width" : 8, "height" : 8, "paletteIndices" : "AQECAgECAgICAgECAQECAQMCAgEBBAEBAwICAQQEBAECAgEEBAUEBAMCAQUFBgUFAgEEBgYGBgYBBAYGBgYGBg==" - }, - "palette" : { - "originalArgb8888" : [ -14145496, -10465232, -7835584, -14133200, -14129088, -12019640 ], - "convertedRgb565" : [ 10565, 25222, -29816, 10950, 11080, 19657 ] } }, "diagnostics" : [ ] @@ -1890,14 +1890,14 @@ "last_modified" : 1776965154263, "fingerprint" : "77c5277220421226d16f58b1bcfb4eaf157fa4f6c740c5aaebefaf88fb91c22e", "metadata" : { + "palette" : { + "originalArgb8888" : [ -10465232, -7835584, -14145496, -12019640, -14133200, -14129088 ], + "convertedRgb565" : [ 25222, -29816, 10565, 19657, 10950, 11080 ] + }, "tile" : { "width" : 8, "height" : 8, "paletteIndices" : "AQECAgMEBAQBAgICAgMEBAECAgICAwQEAQMBAgIDBAQDBQUDAQMEBAUGBQYFBQQEBgQGBAQEBAQEBAQEBAQEBA==" - }, - "palette" : { - "originalArgb8888" : [ -10465232, -7835584, -14145496, -12019640, -14133200, -14129088 ], - "convertedRgb565" : [ 25222, -29816, 10565, 19657, 10950, 11080 ] } }, "diagnostics" : [ ] diff --git a/tools/vscode-extension/out/extension.js b/tools/vscode-extension/out/extension.js index 3baaba89..f967e639 100644 --- a/tools/vscode-extension/out/extension.js +++ b/tools/vscode-extension/out/extension.js @@ -335,4 +335,4 @@ function readObject(value) { } return value; } -//# sourceMappingURL=extension.js.map +//# sourceMappingURL=extension.js.map \ No newline at end of file -- 2.47.2 From 10fd7f611115cc1396bf2e294d57a5db825715bd Mon Sep 17 00:00:00 2001 From: bQUARKz Date: Wed, 6 May 2026 15:46:46 +0100 Subject: [PATCH 27/37] Frontend Visual Theme Spec and Retirement of Host-Consumed Semantic CSS --- .../p/studio/compiler/PBSFrontendThemes.java | 56 +++---- .../studio/compiler/pbs/PbsSemanticKind.java | 7 +- .../PbsSemanticPresentationContractTest.java | 3 +- .../FrontendSemanticPresentationSpec.java | 6 - .../CompilerLanguageServiceBridge.java | 96 +++++++++++- .../CompilerLanguageServiceBridgeTest.java | 18 ++- test-projects/main/.vscode/settings.json | 141 ++++++++++++------ 7 files changed, 241 insertions(+), 86 deletions(-) diff --git a/prometeu-compiler/frontends/prometeu-frontend-pbs/src/main/java/p/studio/compiler/PBSFrontendThemes.java b/prometeu-compiler/frontends/prometeu-frontend-pbs/src/main/java/p/studio/compiler/PBSFrontendThemes.java index 492d342c..03c513c9 100644 --- a/prometeu-compiler/frontends/prometeu-frontend-pbs/src/main/java/p/studio/compiler/PBSFrontendThemes.java +++ b/prometeu-compiler/frontends/prometeu-frontend-pbs/src/main/java/p/studio/compiler/PBSFrontendThemes.java @@ -12,34 +12,34 @@ public class PBSFrontendThemes { "PBS Default", new FrontendEditorPaletteSpec( "#d9e2ec", - "#2d4f6b", - "#2d4f6b", - "#6f8193", - "#2c2140", - "#a47dff", - "#efe6ff"), + "#2f3f5b", + "#23314a", + "#6b7f99", + "#241f38", + "#b392f0", + "#f5efff"), List.of( - new FrontendTokenStyleSpec("pbs-comment", "#c090b0", true, false, false), - new FrontendTokenStyleSpec("pbs-string", "#00c088", false, false, false), - new FrontendTokenStyleSpec("pbs-number", "#ff90b0", false, false, false), - new FrontendTokenStyleSpec("pbs-literal", "#4fc1ff", false, false, false), - new FrontendTokenStyleSpec("pbs-lifecycle", "#ef50c0", false, false, false), - new FrontendTokenStyleSpec("pbs-keyword", "#569cd6", false, false, false), - new FrontendTokenStyleSpec("pbs-operator", "#d4d4d4", false, false, false), - new FrontendTokenStyleSpec("pbs-punctuation", "#d4d4d4", false, false, false), - new FrontendTokenStyleSpec("pbs-function", "#f2c14e", false, false, false), - new FrontendTokenStyleSpec("pbs-method", "#f2c14e", false, false, false), - new FrontendTokenStyleSpec("pbs-constructor", "#ecdcaa", false, false, false), - new FrontendTokenStyleSpec("pbs-struct", "#4ec9b0", false, false, false), - new FrontendTokenStyleSpec("pbs-contract", "#78dce8", false, false, false), - new FrontendTokenStyleSpec("pbs-host", "#b7a2fa", false, false, false), - new FrontendTokenStyleSpec("pbs-builtin-type", "#8be9fd", false, false, false), - new FrontendTokenStyleSpec("pbs-service", "#b7a2fa", false, false, false), - new FrontendTokenStyleSpec("pbs-error", "#ff5b5b", false, false, false), - new FrontendTokenStyleSpec("pbs-enum", "#56cfe1", false, false, false), - new FrontendTokenStyleSpec("pbs-callback", "#b7a2fa", false, false, false), - new FrontendTokenStyleSpec("pbs-global", "#f790fc", true, false, false), - new FrontendTokenStyleSpec("pbs-const", "#f78c6c", false, false, false), - new FrontendTokenStyleSpec("pbs-implements", "#a1c181", false, false, false), + new FrontendTokenStyleSpec("pbs-comment", "#8b949e", true, false, false), + new FrontendTokenStyleSpec("pbs-string", "#7ee787", false, false, false), + new FrontendTokenStyleSpec("pbs-number", "#ffa657", false, false, false), + new FrontendTokenStyleSpec("pbs-literal", "#79c0ff", false, false, false), + new FrontendTokenStyleSpec("pbs-lifecycle", "#ff7b72", false, true, false), + new FrontendTokenStyleSpec("pbs-keyword", "#d2a8ff", false, false, false), + new FrontendTokenStyleSpec("pbs-operator", "#c9d1d9", false, false, false), + new FrontendTokenStyleSpec("pbs-punctuation", "#8b949e", false, false, false), + new FrontendTokenStyleSpec("pbs-function", "#ffa657", false, true, false), + new FrontendTokenStyleSpec("pbs-method", "#ffd580", false, false, false), + new FrontendTokenStyleSpec("pbs-constructor", "#e3b341", false, true, false), + new FrontendTokenStyleSpec("pbs-struct", "#56d4dd", false, false, false), + new FrontendTokenStyleSpec("pbs-contract", "#79c0ff", false, false, true), + new FrontendTokenStyleSpec("pbs-host", "#c297ff", false, false, false), + new FrontendTokenStyleSpec("pbs-builtin-type", "#7ee787", true, false, false), + new FrontendTokenStyleSpec("pbs-service", "#c297ff", false, true, false), + new FrontendTokenStyleSpec("pbs-error", "#ff7b72", false, false, true), + new FrontendTokenStyleSpec("pbs-enum", "#56d4dd", false, true, false), + new FrontendTokenStyleSpec("pbs-callback", "#ffb3e6", false, false, false), + new FrontendTokenStyleSpec("pbs-global", "#f778ba", true, false, false), + new FrontendTokenStyleSpec("pbs-const", "#ffab70", false, true, false), + new FrontendTokenStyleSpec("pbs-implements", "#a5d6ff", false, false, false), new FrontendTokenStyleSpec("pbs-identifier", "#d4d4d4", false, false, false))); } diff --git a/prometeu-compiler/frontends/prometeu-frontend-pbs/src/main/java/p/studio/compiler/pbs/PbsSemanticKind.java b/prometeu-compiler/frontends/prometeu-frontend-pbs/src/main/java/p/studio/compiler/pbs/PbsSemanticKind.java index 0c577e4a..bae8c491 100644 --- a/prometeu-compiler/frontends/prometeu-frontend-pbs/src/main/java/p/studio/compiler/pbs/PbsSemanticKind.java +++ b/prometeu-compiler/frontends/prometeu-frontend-pbs/src/main/java/p/studio/compiler/pbs/PbsSemanticKind.java @@ -51,12 +51,13 @@ public enum PbsSemanticKind { case COMMENT -> COMMENT; case STRING_LITERAL -> STRING; case INT_LITERAL, FLOAT_LITERAL, BOUNDED_LITERAL -> NUMBER; - case TRUE, FALSE, NONE -> LITERAL; + case TRUE, FALSE, NONE, SOME, OK, ERR -> LITERAL; + case VOID, OPTIONAL, RESULT -> BUILTIN_TYPE; case IMPORT, FROM, AS, SERVICE, HOST, FN, APPLY, BIND, NEW, IMPLEMENTS, USING, CTOR, DECLARE, LET, CONST, GLOBAL, STRUCT, CONTRACT, ERROR, ENUM, CALLBACK, BUILTIN, SELF, THIS, PUB, MUT, MOD, TYPE, IF, ELSE, SWITCH, DEFAULT, FOR, UNTIL, STEP, - WHILE, BREAK, CONTINUE, RETURN, VOID, OPTIONAL, RESULT, SOME, OK, ERR, HANDLE, - AND, OR, NOT, SPAWN, YIELD, SLEEP, MATCH -> KEYWORD; + WHILE, BREAK, CONTINUE, RETURN, HANDLE, AND, OR, NOT, SPAWN, YIELD, SLEEP, + MATCH -> KEYWORD; case PLUS, MINUS, STAR, SLASH, PERCENT, BANG, PLUS_EQUAL, MINUS_EQUAL, STAR_EQUAL, SLASH_EQUAL, PERCENT_EQUAL, BANG_EQUAL, EQUAL, EQUAL_EQUAL, LESS, LESS_EQUAL, GREATER, GREATER_EQUAL, AND_AND, OR_OR, ARROW, QUESTION -> OPERATOR; diff --git a/prometeu-compiler/frontends/prometeu-frontend-pbs/src/test/java/p/studio/compiler/pbs/PbsSemanticPresentationContractTest.java b/prometeu-compiler/frontends/prometeu-frontend-pbs/src/test/java/p/studio/compiler/pbs/PbsSemanticPresentationContractTest.java index 3e26eb5e..743b144f 100644 --- a/prometeu-compiler/frontends/prometeu-frontend-pbs/src/test/java/p/studio/compiler/pbs/PbsSemanticPresentationContractTest.java +++ b/prometeu-compiler/frontends/prometeu-frontend-pbs/src/test/java/p/studio/compiler/pbs/PbsSemanticPresentationContractTest.java @@ -20,7 +20,8 @@ final class PbsSemanticPresentationContractTest { assertEquals(1, presentation.themes().size()); assertEquals("PBS Default", presentation.defaultTheme().displayName()); assertEquals("#d9e2ec", presentation.defaultTheme().editorPalette().baseForeground()); - assertEquals("#569cd6", presentation.defaultTheme().requireTokenStyle("pbs-keyword").foreground()); + assertEquals("#d2a8ff", presentation.defaultTheme().requireTokenStyle("pbs-keyword").foreground()); + assertTrue(presentation.defaultTheme().requireTokenStyle("pbs-builtin-type").italic()); assertTrue(presentation.defaultTheme().requireTokenStyle("pbs-comment").italic()); assertEquals(PBSFrontendHostProjections.VSCODE_HOST_ID, presentation.requireHostProjection("vscode").hostId()); } diff --git a/prometeu-compiler/prometeu-compiler-core/src/main/java/p/studio/compiler/models/FrontendSemanticPresentationSpec.java b/prometeu-compiler/prometeu-compiler-core/src/main/java/p/studio/compiler/models/FrontendSemanticPresentationSpec.java index 9a4a6309..69938d91 100644 --- a/prometeu-compiler/prometeu-compiler-core/src/main/java/p/studio/compiler/models/FrontendSemanticPresentationSpec.java +++ b/prometeu-compiler/prometeu-compiler-core/src/main/java/p/studio/compiler/models/FrontendSemanticPresentationSpec.java @@ -8,12 +8,6 @@ public record FrontendSemanticPresentationSpec( String defaultThemeId, List hostProjections) { - public FrontendSemanticPresentationSpec( - final List themes, - final String defaultThemeId) { - this(themes, defaultThemeId, List.of()); - } - public FrontendSemanticPresentationSpec { themes = List.copyOf(Objects.requireNonNull(themes, "themes")); defaultThemeId = Objects.requireNonNull(defaultThemeId, "defaultThemeId").trim(); diff --git a/prometeu-lsp/prometeu-lsp-v1/src/main/java/p/studio/lsp/services/compiler/CompilerLanguageServiceBridge.java b/prometeu-lsp/prometeu-lsp-v1/src/main/java/p/studio/lsp/services/compiler/CompilerLanguageServiceBridge.java index c85617d8..9a2d14a7 100644 --- a/prometeu-lsp/prometeu-lsp-v1/src/main/java/p/studio/lsp/services/compiler/CompilerLanguageServiceBridge.java +++ b/prometeu-lsp/prometeu-lsp-v1/src/main/java/p/studio/lsp/services/compiler/CompilerLanguageServiceBridge.java @@ -14,6 +14,7 @@ import p.studio.compiler.models.FrontendVisualThemeSpec; import p.studio.compiler.pbs.PbsSemanticKind; import p.studio.compiler.pbs.lexer.PbsLexer; import p.studio.compiler.pbs.lexer.PbsToken; +import p.studio.compiler.pbs.lexer.PbsTokenKind; import p.studio.compiler.source.identifiers.FileId; import p.studio.compiler.source.diagnostics.DiagnosticSink; import p.studio.compiler.utilities.SourceProviderFactory; @@ -29,8 +30,11 @@ import java.util.ArrayList; import java.util.List; import java.util.Map; import java.util.Objects; +import java.util.Set; public record CompilerLanguageServiceBridge() implements LanguageServiceBridge { + private static final Set BUILTIN_TYPE_NAMES = Set.of("int", "float", "bool", "string", "i32", "i64", "f32", "f64"); + @Override public BaselineServerDescription describeServer(final LspProjectContext context) { @@ -182,7 +186,97 @@ public record CompilerLanguageServiceBridge() implements LanguageServiceBridge { if (isLifecycleToken(tokens, index, token)) { return PbsSemanticKind.LIFECYCLE; } - return PbsSemanticKind.IDENTIFIER; + return classifyIdentifierToken(tokens, index, token); + } + return null; + } + + private PbsSemanticKind classifyIdentifierToken( + final ReadOnlyList tokens, + final int index, + final PbsToken token) { + final PbsTokenKind previousKind = previousSignificantKind(tokens, index); + final PbsTokenKind nextKind = nextSignificantKind(tokens, index); + + if (previousKind == PbsTokenKind.STRUCT) { + return PbsSemanticKind.STRUCT; + } + if (previousKind == PbsTokenKind.CONTRACT) { + return PbsSemanticKind.CONTRACT; + } + if (previousKind == PbsTokenKind.HOST) { + return PbsSemanticKind.HOST; + } + if (previousKind == PbsTokenKind.SERVICE) { + return PbsSemanticKind.SERVICE; + } + if (previousKind == PbsTokenKind.ENUM || previousKind == PbsTokenKind.ERROR) { + return PbsSemanticKind.ENUM; + } + if (previousKind == PbsTokenKind.CALLBACK) { + return PbsSemanticKind.CALLBACK; + } + if (previousKind == PbsTokenKind.GLOBAL) { + return PbsSemanticKind.GLOBAL; + } + if (previousKind == PbsTokenKind.CONST) { + return PbsSemanticKind.CONST; + } + if (previousKind == PbsTokenKind.CTOR || previousKind == PbsTokenKind.NEW) { + return PbsSemanticKind.CONSTRUCTOR; + } + if (previousKind == PbsTokenKind.BUILTIN) { + return PbsSemanticKind.BUILTIN_TYPE; + } + if (previousKind == PbsTokenKind.DOT && nextKind == PbsTokenKind.LEFT_PAREN) { + return PbsSemanticKind.METHOD; + } + if (nextKind == PbsTokenKind.LEFT_PAREN) { + return PbsSemanticKind.FUNCTION; + } + if (isTypeReferenceContext(previousKind, token.lexeme())) { + return PbsSemanticKind.BUILTIN_TYPE; + } + return PbsSemanticKind.IDENTIFIER; + } + + private boolean isTypeReferenceContext( + final PbsTokenKind previousKind, + final String lexeme) { + if (previousKind == null) { + return false; + } + if (previousKind != PbsTokenKind.COLON + && previousKind != PbsTokenKind.ARROW + && previousKind != PbsTokenKind.AS + && previousKind != PbsTokenKind.IMPLEMENTS) { + return false; + } + return BUILTIN_TYPE_NAMES.contains(lexeme); + } + + private PbsTokenKind previousSignificantKind( + final ReadOnlyList tokens, + final int index) { + for (int cursor = index - 1; cursor >= 0; cursor -= 1) { + final PbsTokenKind kind = tokens.get(cursor).kind(); + if (kind == PbsTokenKind.COMMENT || kind == PbsTokenKind.EOF) { + continue; + } + return kind; + } + return null; + } + + private PbsTokenKind nextSignificantKind( + final ReadOnlyList tokens, + final int index) { + for (int cursor = index + 1; cursor < tokens.size(); cursor += 1) { + final PbsTokenKind kind = tokens.get(cursor).kind(); + if (kind == PbsTokenKind.COMMENT || kind == PbsTokenKind.EOF) { + continue; + } + return kind; } return null; } diff --git a/prometeu-lsp/prometeu-lsp-v1/src/test/java/p/studio/lsp/services/compiler/CompilerLanguageServiceBridgeTest.java b/prometeu-lsp/prometeu-lsp-v1/src/test/java/p/studio/lsp/services/compiler/CompilerLanguageServiceBridgeTest.java index 1c3c0a61..30d03082 100644 --- a/prometeu-lsp/prometeu-lsp-v1/src/test/java/p/studio/lsp/services/compiler/CompilerLanguageServiceBridgeTest.java +++ b/prometeu-lsp/prometeu-lsp-v1/src/test/java/p/studio/lsp/services/compiler/CompilerLanguageServiceBridgeTest.java @@ -46,14 +46,28 @@ class CompilerLanguageServiceBridgeTest { new LspProjectContext("main", "pbs", Path.of(".")), Path.of("demo.pbs").toUri().toString(), """ + struct Vec2 { + fn length() -> int { + return 0; + } + } + fn main() -> void { - const answer = 42; + const answer: int = 42; + let value = new Vec2(); + value.length(); } """); assertTrue(semanticTokens.legend().contains("pbs-keyword")); assertTrue(semanticTokens.tokens().stream().anyMatch(token -> token.semanticKey().equals("pbs-keyword"))); assertTrue(semanticTokens.tokens().stream().anyMatch(token -> token.semanticKey().equals("pbs-number"))); + assertTrue(semanticTokens.tokens().stream().anyMatch(token -> token.semanticKey().equals("pbs-struct"))); + assertTrue(semanticTokens.tokens().stream().anyMatch(token -> token.semanticKey().equals("pbs-function"))); + assertTrue(semanticTokens.tokens().stream().anyMatch(token -> token.semanticKey().equals("pbs-method"))); + assertTrue(semanticTokens.tokens().stream().anyMatch(token -> token.semanticKey().equals("pbs-const"))); + assertTrue(semanticTokens.tokens().stream().anyMatch(token -> token.semanticKey().equals("pbs-builtin-type"))); + assertTrue(semanticTokens.tokens().stream().anyMatch(token -> token.semanticKey().equals("pbs-constructor"))); } @Test @@ -74,7 +88,7 @@ class CompilerLanguageServiceBridgeTest { assertEquals("#d9e2ec", description.visualThemes().getFirst().editorPalette().baseForeground()); assertTrue(description.visualThemes().getFirst().tokenStyles().stream() .anyMatch(tokenStyle -> tokenStyle.semanticKey().equals("pbs-keyword") - && tokenStyle.foreground().equals("#569cd6"))); + && tokenStyle.foreground().equals("#d2a8ff"))); } private Path findRepoRoot(final Path start) { diff --git a/test-projects/main/.vscode/settings.json b/test-projects/main/.vscode/settings.json index afd4ce90..593300da 100644 --- a/test-projects/main/.vscode/settings.json +++ b/test-projects/main/.vscode/settings.json @@ -3,66 +3,117 @@ "enabled": true, "rules": { "pbs-comment:pbs": { - "foreground": "#c090b0", + "foreground": "#8b949e", "italic": true }, - "pbs-string:pbs": "#00c088", - "pbs-number:pbs": "#ff90b0", - "pbs-literal:pbs": "#4fc1ff", - "pbs-lifecycle:pbs": "#ef50c0", - "pbs-keyword:pbs": "#569cd6", - "pbs-operator:pbs": "#d4d4d4", - "pbs-punctuation:pbs": "#d4d4d4", - "pbs-function:pbs": "#f2c14e", - "pbs-method:pbs": "#f2c14e", - "pbs-constructor:pbs": "#ecdcaa", - "pbs-struct:pbs": "#4ec9b0", - "pbs-contract:pbs": "#78dce8", - "pbs-host:pbs": "#b7a2fa", - "pbs-builtin-type:pbs": "#8be9fd", - "pbs-service:pbs": "#b7a2fa", - "pbs-error:pbs": "#ff5b5b", - "pbs-enum:pbs": "#56cfe1", - "pbs-callback:pbs": "#b7a2fa", + "pbs-string:pbs": "#7ee787", + "pbs-number:pbs": "#ffa657", + "pbs-literal:pbs": "#79c0ff", + "pbs-lifecycle:pbs": { + "foreground": "#ff7b72", + "bold": true + }, + "pbs-keyword:pbs": "#d2a8ff", + "pbs-operator:pbs": "#c9d1d9", + "pbs-punctuation:pbs": "#8b949e", + "pbs-function:pbs": { + "foreground": "#ffa657", + "bold": true + }, + "pbs-method:pbs": "#ffd580", + "pbs-constructor:pbs": { + "foreground": "#e3b341", + "bold": true + }, + "pbs-struct:pbs": "#56d4dd", + "pbs-contract:pbs": { + "foreground": "#79c0ff", + "underline": true + }, + "pbs-host:pbs": "#c297ff", + "pbs-builtin-type:pbs": { + "foreground": "#7ee787", + "italic": true + }, + "pbs-service:pbs": { + "foreground": "#c297ff", + "bold": true + }, + "pbs-error:pbs": { + "foreground": "#ff7b72", + "underline": true + }, + "pbs-enum:pbs": { + "foreground": "#56d4dd", + "bold": true + }, + "pbs-callback:pbs": "#ffb3e6", "pbs-global:pbs": { - "foreground": "#f790fc", + "foreground": "#f778ba", "italic": true }, - "pbs-const:pbs": "#f78c6c", - "pbs-implements:pbs": "#a1c181", + "pbs-const:pbs": { + "foreground": "#ffab70", + "bold": true + }, + "pbs-implements:pbs": "#a5d6ff", "pbs-identifier:pbs": "#d4d4d4", "comment:pbs": { - "foreground": "#c090b0", + "foreground": "#8b949e", "italic": true }, - "string:pbs": "#00c088", - "number:pbs": "#ff90b0", - "enumMember:pbs": "#4fc1ff", - "variable:pbs": "#4fc1ff", - "function.async:pbs": "#ef50c0", - "variable.async:pbs": "#ef50c0", - "keyword:pbs": "#569cd6", - "operator:pbs": "#d4d4d4", - "function:pbs": "#f2c14e", - "method:pbs": "#f2c14e", - "class.declaration:pbs": "#ecdcaa", - "type.declaration:pbs": "#ecdcaa", - "struct:pbs": "#4ec9b0", - "type:pbs": "#4ec9b0", - "interface:pbs": "#78dce8", - "class.defaultLibrary:pbs": "#b7a2fa", - "type.defaultLibrary:pbs": "#b7a2fa", - "variable.defaultLibrary:pbs": "#8be9fd", - "enum:pbs": "#ff5b5b", + "string:pbs": "#7ee787", + "number:pbs": "#ffa657", + "enumMember:pbs": "#79c0ff", + "variable:pbs": "#79c0ff", + "function.async:pbs": { + "foreground": "#ff7b72", + "bold": true + }, + "variable.async:pbs": { + "foreground": "#ff7b72", + "bold": true + }, + "keyword:pbs": "#d2a8ff", + "operator:pbs": "#c9d1d9", + "function:pbs": { + "foreground": "#ffa657", + "bold": true + }, + "method:pbs": "#ffd580", + "class.declaration:pbs": { + "foreground": "#e3b341", + "bold": true + }, + "type.declaration:pbs": { + "foreground": "#e3b341", + "bold": true + }, + "struct:pbs": "#56d4dd", + "type:pbs": "#56d4dd", + "interface:pbs": { + "foreground": "#79c0ff", + "underline": true + }, + "class.defaultLibrary:pbs": "#c297ff", + "type.defaultLibrary:pbs": "#c297ff", + "variable.defaultLibrary:pbs": { + "foreground": "#7ee787", + "italic": true + }, + "enum:pbs": { + "foreground": "#ff7b72", + "underline": true + }, "variable.readonly:pbs": { - "foreground": "#f790fc", + "foreground": "#f778ba", "italic": true } } }, "workbench.colorCustomizations": { "editor.foreground": "#d9e2ec", - "editor.selectionBackground": "#2d4f6b", - "editorLineNumber.foreground": "#6f8193" + "editor.selectionBackground": "#2f3f5b", + "editorLineNumber.foreground": "#6b7f99" } } \ No newline at end of file -- 2.47.2 From e23367b0227a0f76d6e709b2d6003a16db76efdf Mon Sep 17 00:00:00 2001 From: bQUARKz Date: Wed, 6 May 2026 15:50:35 +0100 Subject: [PATCH 28/37] Frontend Visual Theme Spec and Retirement of Host-Consumed Semantic CSS --- .../p/studio/compiler/PBSDefinitions.java | 1 + .../compiler/PBSSemanticTokenProvider.java | 158 +++++++++++++++++ .../PbsSemanticPresentationContractTest.java | 23 +++ .../models/FrontendSemanticToken.java | 29 +++ .../models/FrontendSemanticTokenProvider.java | 14 ++ .../studio/compiler/models/FrontendSpec.java | 2 + prometeu-lsp/prometeu-lsp-v1/build.gradle.kts | 2 +- .../CompilerLanguageServiceBridge.java | 165 ++---------------- 8 files changed, 247 insertions(+), 147 deletions(-) create mode 100644 prometeu-compiler/frontends/prometeu-frontend-pbs/src/main/java/p/studio/compiler/PBSSemanticTokenProvider.java create mode 100644 prometeu-compiler/prometeu-compiler-core/src/main/java/p/studio/compiler/models/FrontendSemanticToken.java create mode 100644 prometeu-compiler/prometeu-compiler-core/src/main/java/p/studio/compiler/models/FrontendSemanticTokenProvider.java diff --git a/prometeu-compiler/frontends/prometeu-frontend-pbs/src/main/java/p/studio/compiler/PBSDefinitions.java b/prometeu-compiler/frontends/prometeu-frontend-pbs/src/main/java/p/studio/compiler/PBSDefinitions.java index e55a89ef..ea3135f3 100644 --- a/prometeu-compiler/frontends/prometeu-frontend-pbs/src/main/java/p/studio/compiler/PBSDefinitions.java +++ b/prometeu-compiler/frontends/prometeu-frontend-pbs/src/main/java/p/studio/compiler/PBSDefinitions.java @@ -17,5 +17,6 @@ public class PBSDefinitions { List.of(PBSFrontendThemes.DEFAULT_PBS), "pbs-default", List.of(PBSFrontendHostProjections.VSCODE))) + .semanticTokenProvider(new PBSSemanticTokenProvider()) .build(); } diff --git a/prometeu-compiler/frontends/prometeu-frontend-pbs/src/main/java/p/studio/compiler/PBSSemanticTokenProvider.java b/prometeu-compiler/frontends/prometeu-frontend-pbs/src/main/java/p/studio/compiler/PBSSemanticTokenProvider.java new file mode 100644 index 00000000..b9c082e5 --- /dev/null +++ b/prometeu-compiler/frontends/prometeu-frontend-pbs/src/main/java/p/studio/compiler/PBSSemanticTokenProvider.java @@ -0,0 +1,158 @@ +package p.studio.compiler; + +import p.studio.compiler.models.FrontendSemanticToken; +import p.studio.compiler.models.FrontendSemanticTokenProvider; +import p.studio.compiler.pbs.PbsSemanticKind; +import p.studio.compiler.pbs.lexer.PbsLexer; +import p.studio.compiler.pbs.lexer.PbsToken; +import p.studio.compiler.pbs.lexer.PbsTokenKind; +import p.studio.compiler.source.diagnostics.DiagnosticSink; +import p.studio.compiler.source.identifiers.FileId; +import p.studio.utilities.structures.ReadOnlyList; + +import java.util.ArrayList; +import java.util.List; +import java.util.Set; + +public final class PBSSemanticTokenProvider implements FrontendSemanticTokenProvider { + private static final Set BUILTIN_TYPE_NAMES = Set.of("int", "float", "bool", "string", "i32", "i64", "f32", "f64"); + + @Override + public List tokenize(final String documentText) { + final String effectiveText = documentText == null ? "" : documentText; + final ReadOnlyList tokens = PbsLexer.lex(effectiveText, FileId.none(), DiagnosticSink.empty()); + final ArrayList semanticTokens = new ArrayList<>(); + + for (int index = 0; index < tokens.size(); index += 1) { + final PbsToken token = tokens.get(index); + final PbsSemanticKind semanticKind = classifyToken(tokens, index); + if (semanticKind == null) { + continue; + } + semanticTokens.add(new FrontendSemanticToken(token.start(), token.end(), semanticKind.semanticKey())); + } + + return List.copyOf(semanticTokens); + } + + private PbsSemanticKind classifyToken( + final ReadOnlyList tokens, + final int index) { + final PbsToken token = tokens.get(index); + final PbsSemanticKind lexicalKind = PbsSemanticKind.forToken(token); + if (lexicalKind != null) { + return lexicalKind; + } + if (token.kind() == PbsTokenKind.IDENTIFIER) { + if (isLifecycleToken(tokens, index, token)) { + return PbsSemanticKind.LIFECYCLE; + } + return classifyIdentifierToken(tokens, index, token); + } + return null; + } + + private PbsSemanticKind classifyIdentifierToken( + final ReadOnlyList tokens, + final int index, + final PbsToken token) { + final PbsTokenKind previousKind = previousSignificantKind(tokens, index); + final PbsTokenKind nextKind = nextSignificantKind(tokens, index); + + if (previousKind == PbsTokenKind.STRUCT) { + return PbsSemanticKind.STRUCT; + } + if (previousKind == PbsTokenKind.CONTRACT) { + return PbsSemanticKind.CONTRACT; + } + if (previousKind == PbsTokenKind.HOST) { + return PbsSemanticKind.HOST; + } + if (previousKind == PbsTokenKind.SERVICE) { + return PbsSemanticKind.SERVICE; + } + if (previousKind == PbsTokenKind.ENUM || previousKind == PbsTokenKind.ERROR) { + return PbsSemanticKind.ENUM; + } + if (previousKind == PbsTokenKind.CALLBACK) { + return PbsSemanticKind.CALLBACK; + } + if (previousKind == PbsTokenKind.GLOBAL) { + return PbsSemanticKind.GLOBAL; + } + if (previousKind == PbsTokenKind.CONST) { + return PbsSemanticKind.CONST; + } + if (previousKind == PbsTokenKind.CTOR || previousKind == PbsTokenKind.NEW) { + return PbsSemanticKind.CONSTRUCTOR; + } + if (previousKind == PbsTokenKind.BUILTIN) { + return PbsSemanticKind.BUILTIN_TYPE; + } + if (previousKind == PbsTokenKind.DOT && nextKind == PbsTokenKind.LEFT_PAREN) { + return PbsSemanticKind.METHOD; + } + if (nextKind == PbsTokenKind.LEFT_PAREN) { + return PbsSemanticKind.FUNCTION; + } + if (isTypeReferenceContext(previousKind, token.lexeme())) { + return PbsSemanticKind.BUILTIN_TYPE; + } + return PbsSemanticKind.IDENTIFIER; + } + + private boolean isTypeReferenceContext( + final PbsTokenKind previousKind, + final String lexeme) { + if (previousKind == null) { + return false; + } + if (previousKind != PbsTokenKind.COLON + && previousKind != PbsTokenKind.ARROW + && previousKind != PbsTokenKind.AS + && previousKind != PbsTokenKind.IMPLEMENTS) { + return false; + } + return BUILTIN_TYPE_NAMES.contains(lexeme); + } + + private PbsTokenKind previousSignificantKind( + final ReadOnlyList tokens, + final int index) { + for (int cursor = index - 1; cursor >= 0; cursor -= 1) { + final PbsTokenKind kind = tokens.get(cursor).kind(); + if (kind == PbsTokenKind.COMMENT || kind == PbsTokenKind.EOF) { + continue; + } + return kind; + } + return null; + } + + private PbsTokenKind nextSignificantKind( + final ReadOnlyList tokens, + final int index) { + for (int cursor = index + 1; cursor < tokens.size(); cursor += 1) { + final PbsTokenKind kind = tokens.get(cursor).kind(); + if (kind == PbsTokenKind.COMMENT || kind == PbsTokenKind.EOF) { + continue; + } + return kind; + } + return null; + } + + private boolean isLifecycleToken( + final ReadOnlyList tokens, + final int index, + final PbsToken token) { + if (!"Init".equals(token.lexeme()) && !"Frame".equals(token.lexeme())) { + return false; + } + if (index == 0 || index + 1 >= tokens.size()) { + return false; + } + return tokens.get(index - 1).kind() == PbsTokenKind.LEFT_BRACKET + && tokens.get(index + 1).kind() == PbsTokenKind.RIGHT_BRACKET; + } +} diff --git a/prometeu-compiler/frontends/prometeu-frontend-pbs/src/test/java/p/studio/compiler/pbs/PbsSemanticPresentationContractTest.java b/prometeu-compiler/frontends/prometeu-frontend-pbs/src/test/java/p/studio/compiler/pbs/PbsSemanticPresentationContractTest.java index 743b144f..6ef7400b 100644 --- a/prometeu-compiler/frontends/prometeu-frontend-pbs/src/test/java/p/studio/compiler/pbs/PbsSemanticPresentationContractTest.java +++ b/prometeu-compiler/frontends/prometeu-frontend-pbs/src/test/java/p/studio/compiler/pbs/PbsSemanticPresentationContractTest.java @@ -3,6 +3,9 @@ package p.studio.compiler.pbs; import org.junit.jupiter.api.Test; import p.studio.compiler.PBSFrontendHostProjections; import p.studio.compiler.PBSDefinitions; +import p.studio.compiler.models.FrontendSemanticToken; + +import java.util.List; import static org.junit.jupiter.api.Assertions.assertEquals; import static org.junit.jupiter.api.Assertions.assertFalse; @@ -50,4 +53,24 @@ final class PbsSemanticPresentationContractTest { java.util.List.of("readonly"), vscodeProjection.requireProjection(PbsSemanticKind.GLOBAL.semanticKey()).hostTokenModifiers()); } + + @Test + void shouldPublishPbsOwnedSemanticTokenProvider() { + final List semanticTokens = PBSDefinitions.PBS.getSemanticTokenProvider().tokenize(""" + struct Vec2 {} + + fn main() -> void { + const answer: int = 42; + let value = new Vec2(); + value.length(); + } + """); + + assertTrue(semanticTokens.stream().anyMatch(token -> token.semanticKey().equals(PbsSemanticKind.STRUCT.semanticKey()))); + assertTrue(semanticTokens.stream().anyMatch(token -> token.semanticKey().equals(PbsSemanticKind.FUNCTION.semanticKey()))); + assertTrue(semanticTokens.stream().anyMatch(token -> token.semanticKey().equals(PbsSemanticKind.CONST.semanticKey()))); + assertTrue(semanticTokens.stream().anyMatch(token -> token.semanticKey().equals(PbsSemanticKind.BUILTIN_TYPE.semanticKey()))); + assertTrue(semanticTokens.stream().anyMatch(token -> token.semanticKey().equals(PbsSemanticKind.CONSTRUCTOR.semanticKey()))); + assertTrue(semanticTokens.stream().anyMatch(token -> token.semanticKey().equals(PbsSemanticKind.METHOD.semanticKey()))); + } } diff --git a/prometeu-compiler/prometeu-compiler-core/src/main/java/p/studio/compiler/models/FrontendSemanticToken.java b/prometeu-compiler/prometeu-compiler-core/src/main/java/p/studio/compiler/models/FrontendSemanticToken.java new file mode 100644 index 00000000..fef83228 --- /dev/null +++ b/prometeu-compiler/prometeu-compiler-core/src/main/java/p/studio/compiler/models/FrontendSemanticToken.java @@ -0,0 +1,29 @@ +package p.studio.compiler.models; + +import java.util.Objects; + +public record FrontendSemanticToken( + int startOffset, + int endOffset, + String semanticKey) { + + public FrontendSemanticToken { + if (startOffset < 0) { + throw new IllegalArgumentException("startOffset must be >= 0"); + } + if (endOffset < startOffset) { + throw new IllegalArgumentException("endOffset must be >= startOffset"); + } + semanticKey = requireText(semanticKey, "semanticKey"); + } + + private static String requireText( + final String value, + final String field) { + final String candidate = Objects.requireNonNull(value, field).trim(); + if (candidate.isEmpty()) { + throw new IllegalArgumentException(field + " must not be blank"); + } + return candidate; + } +} diff --git a/prometeu-compiler/prometeu-compiler-core/src/main/java/p/studio/compiler/models/FrontendSemanticTokenProvider.java b/prometeu-compiler/prometeu-compiler-core/src/main/java/p/studio/compiler/models/FrontendSemanticTokenProvider.java new file mode 100644 index 00000000..6e52f6f3 --- /dev/null +++ b/prometeu-compiler/prometeu-compiler-core/src/main/java/p/studio/compiler/models/FrontendSemanticTokenProvider.java @@ -0,0 +1,14 @@ +package p.studio.compiler.models; + +import java.util.List; + +@FunctionalInterface +public interface FrontendSemanticTokenProvider { + FrontendSemanticTokenProvider NOOP = documentText -> List.of(); + + List tokenize(String documentText); + + static FrontendSemanticTokenProvider noop() { + return NOOP; + } +} diff --git a/prometeu-compiler/prometeu-compiler-core/src/main/java/p/studio/compiler/models/FrontendSpec.java b/prometeu-compiler/prometeu-compiler-core/src/main/java/p/studio/compiler/models/FrontendSpec.java index f09e24fc..72a42cab 100644 --- a/prometeu-compiler/prometeu-compiler-core/src/main/java/p/studio/compiler/models/FrontendSpec.java +++ b/prometeu-compiler/prometeu-compiler-core/src/main/java/p/studio/compiler/models/FrontendSpec.java @@ -17,6 +17,8 @@ public class FrontendSpec { private final List stdlibVersions = List.of(); @Builder.Default private final FrontendSemanticPresentationSpec semanticPresentation = FrontendSemanticPresentationSpec.empty(); + @Builder.Default + private final FrontendSemanticTokenProvider semanticTokenProvider = FrontendSemanticTokenProvider.noop(); public String toString() { return String.format("FrontendSpec(language=%s)", languageId); diff --git a/prometeu-lsp/prometeu-lsp-v1/build.gradle.kts b/prometeu-lsp/prometeu-lsp-v1/build.gradle.kts index a7ccc7b3..addf13e3 100644 --- a/prometeu-lsp/prometeu-lsp-v1/build.gradle.kts +++ b/prometeu-lsp/prometeu-lsp-v1/build.gradle.kts @@ -6,6 +6,6 @@ dependencies { implementation(project(":prometeu-lsp:prometeu-lsp-api")) implementation(project(":prometeu-compiler:prometeu-compiler-core")) implementation(project(":prometeu-compiler:prometeu-build-pipeline")) - implementation(project(":prometeu-compiler:frontends:prometeu-frontend-pbs")) + implementation(project(":prometeu-compiler:prometeu-frontend-registry")) implementation(libs.lsp4j) } diff --git a/prometeu-lsp/prometeu-lsp-v1/src/main/java/p/studio/lsp/services/compiler/CompilerLanguageServiceBridge.java b/prometeu-lsp/prometeu-lsp-v1/src/main/java/p/studio/lsp/services/compiler/CompilerLanguageServiceBridge.java index 9a2d14a7..8152a91d 100644 --- a/prometeu-lsp/prometeu-lsp-v1/src/main/java/p/studio/lsp/services/compiler/CompilerLanguageServiceBridge.java +++ b/prometeu-lsp/prometeu-lsp-v1/src/main/java/p/studio/lsp/services/compiler/CompilerLanguageServiceBridge.java @@ -1,6 +1,7 @@ package p.studio.lsp.services.compiler; import org.apache.commons.lang3.StringUtils; +import p.studio.compiler.FrontendRegistryService; import p.studio.compiler.messages.BuilderPipelineConfig; import p.studio.compiler.messages.BuildingIssue; import p.studio.compiler.models.AnalysisSnapshot; @@ -8,21 +9,16 @@ import p.studio.compiler.models.BuilderPipelineContext; import p.studio.compiler.models.FrontendEditorPaletteSpec; import p.studio.compiler.models.FrontendHostProjectionEntrySpec; import p.studio.compiler.models.FrontendHostProjectionSpec; -import p.studio.compiler.PBSDefinitions; +import p.studio.compiler.models.FrontendSemanticPresentationSpec; +import p.studio.compiler.models.FrontendSemanticToken; import p.studio.compiler.models.FrontendTokenStyleSpec; import p.studio.compiler.models.FrontendVisualThemeSpec; -import p.studio.compiler.pbs.PbsSemanticKind; -import p.studio.compiler.pbs.lexer.PbsLexer; -import p.studio.compiler.pbs.lexer.PbsToken; -import p.studio.compiler.pbs.lexer.PbsTokenKind; import p.studio.compiler.source.identifiers.FileId; -import p.studio.compiler.source.diagnostics.DiagnosticSink; import p.studio.compiler.utilities.SourceProviderFactory; import p.studio.compiler.workspaces.BuilderPipelineService; import p.studio.lsp.messages.*; import p.studio.lsp.services.LanguageServiceBridge; import p.studio.utilities.logs.LogAggregator; -import p.studio.utilities.structures.ReadOnlyList; import java.net.URI; import java.nio.file.Path; @@ -30,16 +26,13 @@ import java.util.ArrayList; import java.util.List; import java.util.Map; import java.util.Objects; -import java.util.Set; - -public record CompilerLanguageServiceBridge() implements LanguageServiceBridge { - private static final Set BUILTIN_TYPE_NAMES = Set.of("int", "float", "bool", "string", "i32", "i64", "f32", "f64"); - +public final class CompilerLanguageServiceBridge implements LanguageServiceBridge { @Override public BaselineServerDescription describeServer(final LspProjectContext context) { Objects.requireNonNull(context, "context"); - final var presentation = PBSDefinitions.PBS.getSemanticPresentation(); + final var frontend = frontendSpec(context); + final var presentation = frontend.getSemanticPresentation(); return new BaselineServerDescription( "Prometeu Studio LSP", "0.1.0", @@ -86,28 +79,24 @@ public record CompilerLanguageServiceBridge() implements LanguageServiceBridge { final String text) { Objects.requireNonNull(context, "context"); final String effectiveText = text == null ? "" : text; - final var legend = PBSDefinitions.PBS.getSemanticPresentation().semanticKeys(); - final var tokens = PbsLexer.lex(effectiveText, FileId.none(), DiagnosticSink.empty()); + final var frontend = frontendSpec(context); + final FrontendSemanticPresentationSpec presentation = frontend.getSemanticPresentation(); + final List tokens = frontend.getSemanticTokenProvider().tokenize(effectiveText); final var positionMapper = new DocumentPositionMapper(effectiveText); final var semanticTokens = new ArrayList(); - for (int index = 0; index < tokens.size(); index += 1) { - final PbsToken token = tokens.get(index); - final PbsSemanticKind semanticKind = classifyToken(tokens, index); - if (semanticKind == null) { - continue; - } - final DocumentPosition start = positionMapper.positionOf(token.start()); - final DocumentPosition end = positionMapper.positionOf(token.end()); + for (final FrontendSemanticToken token : tokens) { + final DocumentPosition start = positionMapper.positionOf(token.startOffset()); + final DocumentPosition end = positionMapper.positionOf(token.endOffset()); final int length = Math.max(1, end.character() - start.character()); semanticTokens.add(new BaselineSemanticToken( start.line(), start.character(), length, - semanticKind.semanticKey())); + token.semanticKey())); } - return new BaselineSemanticTokens(legend, semanticTokens); + return new BaselineSemanticTokens(presentation.semanticKeys(), semanticTokens); } @Override @@ -174,127 +163,6 @@ public record CompilerLanguageServiceBridge() implements LanguageServiceBridge { return Path.of(URI.create(Objects.requireNonNull(documentUri, "documentUri"))).toAbsolutePath().normalize(); } - private PbsSemanticKind classifyToken( - final ReadOnlyList tokens, - final int index) { - final PbsToken token = tokens.get(index); - final PbsSemanticKind lexicalKind = PbsSemanticKind.forToken(token); - if (lexicalKind != null) { - return lexicalKind; - } - if (token.kind() == p.studio.compiler.pbs.lexer.PbsTokenKind.IDENTIFIER) { - if (isLifecycleToken(tokens, index, token)) { - return PbsSemanticKind.LIFECYCLE; - } - return classifyIdentifierToken(tokens, index, token); - } - return null; - } - - private PbsSemanticKind classifyIdentifierToken( - final ReadOnlyList tokens, - final int index, - final PbsToken token) { - final PbsTokenKind previousKind = previousSignificantKind(tokens, index); - final PbsTokenKind nextKind = nextSignificantKind(tokens, index); - - if (previousKind == PbsTokenKind.STRUCT) { - return PbsSemanticKind.STRUCT; - } - if (previousKind == PbsTokenKind.CONTRACT) { - return PbsSemanticKind.CONTRACT; - } - if (previousKind == PbsTokenKind.HOST) { - return PbsSemanticKind.HOST; - } - if (previousKind == PbsTokenKind.SERVICE) { - return PbsSemanticKind.SERVICE; - } - if (previousKind == PbsTokenKind.ENUM || previousKind == PbsTokenKind.ERROR) { - return PbsSemanticKind.ENUM; - } - if (previousKind == PbsTokenKind.CALLBACK) { - return PbsSemanticKind.CALLBACK; - } - if (previousKind == PbsTokenKind.GLOBAL) { - return PbsSemanticKind.GLOBAL; - } - if (previousKind == PbsTokenKind.CONST) { - return PbsSemanticKind.CONST; - } - if (previousKind == PbsTokenKind.CTOR || previousKind == PbsTokenKind.NEW) { - return PbsSemanticKind.CONSTRUCTOR; - } - if (previousKind == PbsTokenKind.BUILTIN) { - return PbsSemanticKind.BUILTIN_TYPE; - } - if (previousKind == PbsTokenKind.DOT && nextKind == PbsTokenKind.LEFT_PAREN) { - return PbsSemanticKind.METHOD; - } - if (nextKind == PbsTokenKind.LEFT_PAREN) { - return PbsSemanticKind.FUNCTION; - } - if (isTypeReferenceContext(previousKind, token.lexeme())) { - return PbsSemanticKind.BUILTIN_TYPE; - } - return PbsSemanticKind.IDENTIFIER; - } - - private boolean isTypeReferenceContext( - final PbsTokenKind previousKind, - final String lexeme) { - if (previousKind == null) { - return false; - } - if (previousKind != PbsTokenKind.COLON - && previousKind != PbsTokenKind.ARROW - && previousKind != PbsTokenKind.AS - && previousKind != PbsTokenKind.IMPLEMENTS) { - return false; - } - return BUILTIN_TYPE_NAMES.contains(lexeme); - } - - private PbsTokenKind previousSignificantKind( - final ReadOnlyList tokens, - final int index) { - for (int cursor = index - 1; cursor >= 0; cursor -= 1) { - final PbsTokenKind kind = tokens.get(cursor).kind(); - if (kind == PbsTokenKind.COMMENT || kind == PbsTokenKind.EOF) { - continue; - } - return kind; - } - return null; - } - - private PbsTokenKind nextSignificantKind( - final ReadOnlyList tokens, - final int index) { - for (int cursor = index + 1; cursor < tokens.size(); cursor += 1) { - final PbsTokenKind kind = tokens.get(cursor).kind(); - if (kind == PbsTokenKind.COMMENT || kind == PbsTokenKind.EOF) { - continue; - } - return kind; - } - return null; - } - - private boolean isLifecycleToken( - final ReadOnlyList tokens, - final int index, - final PbsToken token) { - if (!"Init".equals(token.lexeme()) && !"Frame".equals(token.lexeme())) { - return false; - } - if (index == 0 || index + 1 >= tokens.size()) { - return false; - } - return tokens.get(index - 1).kind() == p.studio.compiler.pbs.lexer.PbsTokenKind.LEFT_BRACKET - && tokens.get(index + 1).kind() == p.studio.compiler.pbs.lexer.PbsTokenKind.RIGHT_BRACKET; - } - private BaselineVisualTheme mapVisualTheme(final FrontendVisualThemeSpec theme) { return new BaselineVisualTheme( theme.themeId(), @@ -337,4 +205,9 @@ public record CompilerLanguageServiceBridge() implements LanguageServiceBridge { tokenStyle.bold(), tokenStyle.underline()); } + + private p.studio.compiler.models.FrontendSpec frontendSpec(final LspProjectContext context) { + return FrontendRegistryService.getFrontendSpec(context.languageId()) + .orElseThrow(() -> new IllegalArgumentException("no frontend registered for languageId: " + context.languageId())); + } } -- 2.47.2 From dfad621d054804dfbbf307202cdd01ccaecc1eeb Mon Sep 17 00:00:00 2001 From: bQUARKz Date: Wed, 6 May 2026 17:20:38 +0100 Subject: [PATCH 29/37] Frontend Visual Theme Spec and Retirement of Host-Consumed Semantic CSS --- .../p/studio/compiler/PBSFrontendThemes.java | 2 +- .../compiler/PBSSemanticTokenProvider.java | 57 +++++++++++++++++-- .../PbsSemanticPresentationContractTest.java | 10 ++++ .../CompilerLanguageServiceBridgeTest.java | 10 ++++ test-projects/main/.vscode/settings.json | 2 +- 5 files changed, 75 insertions(+), 6 deletions(-) diff --git a/prometeu-compiler/frontends/prometeu-frontend-pbs/src/main/java/p/studio/compiler/PBSFrontendThemes.java b/prometeu-compiler/frontends/prometeu-frontend-pbs/src/main/java/p/studio/compiler/PBSFrontendThemes.java index 03c513c9..1951d704 100644 --- a/prometeu-compiler/frontends/prometeu-frontend-pbs/src/main/java/p/studio/compiler/PBSFrontendThemes.java +++ b/prometeu-compiler/frontends/prometeu-frontend-pbs/src/main/java/p/studio/compiler/PBSFrontendThemes.java @@ -34,7 +34,7 @@ public class PBSFrontendThemes { new FrontendTokenStyleSpec("pbs-contract", "#79c0ff", false, false, true), new FrontendTokenStyleSpec("pbs-host", "#c297ff", false, false, false), new FrontendTokenStyleSpec("pbs-builtin-type", "#7ee787", true, false, false), - new FrontendTokenStyleSpec("pbs-service", "#c297ff", false, true, false), + new FrontendTokenStyleSpec("pbs-service", "#ff8e7a", false, true, false), new FrontendTokenStyleSpec("pbs-error", "#ff7b72", false, false, true), new FrontendTokenStyleSpec("pbs-enum", "#56d4dd", false, true, false), new FrontendTokenStyleSpec("pbs-callback", "#ffb3e6", false, false, false), diff --git a/prometeu-compiler/frontends/prometeu-frontend-pbs/src/main/java/p/studio/compiler/PBSSemanticTokenProvider.java b/prometeu-compiler/frontends/prometeu-frontend-pbs/src/main/java/p/studio/compiler/PBSSemanticTokenProvider.java index b9c082e5..8e177534 100644 --- a/prometeu-compiler/frontends/prometeu-frontend-pbs/src/main/java/p/studio/compiler/PBSSemanticTokenProvider.java +++ b/prometeu-compiler/frontends/prometeu-frontend-pbs/src/main/java/p/studio/compiler/PBSSemanticTokenProvider.java @@ -11,7 +11,9 @@ import p.studio.compiler.source.identifiers.FileId; import p.studio.utilities.structures.ReadOnlyList; import java.util.ArrayList; +import java.util.HashMap; import java.util.List; +import java.util.Map; import java.util.Set; public final class PBSSemanticTokenProvider implements FrontendSemanticTokenProvider { @@ -21,11 +23,12 @@ public final class PBSSemanticTokenProvider implements FrontendSemanticTokenProv public List tokenize(final String documentText) { final String effectiveText = documentText == null ? "" : documentText; final ReadOnlyList tokens = PbsLexer.lex(effectiveText, FileId.none(), DiagnosticSink.empty()); + final Map declaredKindsByName = collectDeclaredKinds(tokens); final ArrayList semanticTokens = new ArrayList<>(); for (int index = 0; index < tokens.size(); index += 1) { final PbsToken token = tokens.get(index); - final PbsSemanticKind semanticKind = classifyToken(tokens, index); + final PbsSemanticKind semanticKind = classifyToken(tokens, index, declaredKindsByName); if (semanticKind == null) { continue; } @@ -37,7 +40,8 @@ public final class PBSSemanticTokenProvider implements FrontendSemanticTokenProv private PbsSemanticKind classifyToken( final ReadOnlyList tokens, - final int index) { + final int index, + final Map declaredKindsByName) { final PbsToken token = tokens.get(index); final PbsSemanticKind lexicalKind = PbsSemanticKind.forToken(token); if (lexicalKind != null) { @@ -47,7 +51,7 @@ public final class PBSSemanticTokenProvider implements FrontendSemanticTokenProv if (isLifecycleToken(tokens, index, token)) { return PbsSemanticKind.LIFECYCLE; } - return classifyIdentifierToken(tokens, index, token); + return classifyIdentifierToken(tokens, index, token, declaredKindsByName); } return null; } @@ -55,7 +59,8 @@ public final class PBSSemanticTokenProvider implements FrontendSemanticTokenProv private PbsSemanticKind classifyIdentifierToken( final ReadOnlyList tokens, final int index, - final PbsToken token) { + final PbsToken token, + final Map declaredKindsByName) { final PbsTokenKind previousKind = previousSignificantKind(tokens, index); final PbsTokenKind nextKind = nextSignificantKind(tokens, index); @@ -89,6 +94,17 @@ public final class PBSSemanticTokenProvider implements FrontendSemanticTokenProv if (previousKind == PbsTokenKind.BUILTIN) { return PbsSemanticKind.BUILTIN_TYPE; } + final PbsSemanticKind declaredKind = declaredKindsByName.get(token.lexeme()); + if (declaredKind != null) { + if (previousKind == PbsTokenKind.DOT && nextKind == PbsTokenKind.LEFT_PAREN) { + return PbsSemanticKind.METHOD; + } + if (nextKind == PbsTokenKind.DOT + || previousKind == PbsTokenKind.NEW + || isTypeReferenceContext(previousKind, token.lexeme())) { + return declaredKind; + } + } if (previousKind == PbsTokenKind.DOT && nextKind == PbsTokenKind.LEFT_PAREN) { return PbsSemanticKind.METHOD; } @@ -101,6 +117,39 @@ public final class PBSSemanticTokenProvider implements FrontendSemanticTokenProv return PbsSemanticKind.IDENTIFIER; } + private Map collectDeclaredKinds(final ReadOnlyList tokens) { + final Map declaredKindsByName = new HashMap<>(); + for (int index = 0; index < tokens.size() - 1; index += 1) { + final PbsToken token = tokens.get(index); + final PbsToken nextToken = tokens.get(index + 1); + if (nextToken.kind() != PbsTokenKind.IDENTIFIER) { + continue; + } + final PbsSemanticKind declarationKind = declarationKind(token.kind()); + if (declarationKind == null) { + continue; + } + declaredKindsByName.put(nextToken.lexeme(), declarationKind); + } + return Map.copyOf(declaredKindsByName); + } + + private PbsSemanticKind declarationKind(final PbsTokenKind kind) { + return switch (kind) { + case STRUCT -> PbsSemanticKind.STRUCT; + case CONTRACT -> PbsSemanticKind.CONTRACT; + case HOST -> PbsSemanticKind.HOST; + case SERVICE -> PbsSemanticKind.SERVICE; + case ENUM, ERROR -> PbsSemanticKind.ENUM; + case CALLBACK -> PbsSemanticKind.CALLBACK; + case GLOBAL -> PbsSemanticKind.GLOBAL; + case CONST -> PbsSemanticKind.CONST; + case CTOR -> PbsSemanticKind.CONSTRUCTOR; + case BUILTIN -> PbsSemanticKind.BUILTIN_TYPE; + default -> null; + }; + } + private boolean isTypeReferenceContext( final PbsTokenKind previousKind, final String lexeme) { diff --git a/prometeu-compiler/frontends/prometeu-frontend-pbs/src/test/java/p/studio/compiler/pbs/PbsSemanticPresentationContractTest.java b/prometeu-compiler/frontends/prometeu-frontend-pbs/src/test/java/p/studio/compiler/pbs/PbsSemanticPresentationContractTest.java index 6ef7400b..ff28d4ae 100644 --- a/prometeu-compiler/frontends/prometeu-frontend-pbs/src/test/java/p/studio/compiler/pbs/PbsSemanticPresentationContractTest.java +++ b/prometeu-compiler/frontends/prometeu-frontend-pbs/src/test/java/p/studio/compiler/pbs/PbsSemanticPresentationContractTest.java @@ -24,6 +24,7 @@ final class PbsSemanticPresentationContractTest { assertEquals("PBS Default", presentation.defaultTheme().displayName()); assertEquals("#d9e2ec", presentation.defaultTheme().editorPalette().baseForeground()); assertEquals("#d2a8ff", presentation.defaultTheme().requireTokenStyle("pbs-keyword").foreground()); + assertEquals("#ff8e7a", presentation.defaultTheme().requireTokenStyle("pbs-service").foreground()); assertTrue(presentation.defaultTheme().requireTokenStyle("pbs-builtin-type").italic()); assertTrue(presentation.defaultTheme().requireTokenStyle("pbs-comment").italic()); assertEquals(PBSFrontendHostProjections.VSCODE_HOST_ID, presentation.requireHostProjection("vscode").hostId()); @@ -58,11 +59,17 @@ final class PbsSemanticPresentationContractTest { void shouldPublishPbsOwnedSemanticTokenProvider() { final List semanticTokens = PBSDefinitions.PBS.getSemanticTokenProvider().tokenize(""" struct Vec2 {} + service Log {} + host Input {} + enum ResultKind { Ok = 1; } fn main() -> void { const answer: int = 42; let value = new Vec2(); value.length(); + Log.info(); + Input.read(); + let kind: ResultKind; } """); @@ -72,5 +79,8 @@ final class PbsSemanticPresentationContractTest { assertTrue(semanticTokens.stream().anyMatch(token -> token.semanticKey().equals(PbsSemanticKind.BUILTIN_TYPE.semanticKey()))); assertTrue(semanticTokens.stream().anyMatch(token -> token.semanticKey().equals(PbsSemanticKind.CONSTRUCTOR.semanticKey()))); assertTrue(semanticTokens.stream().anyMatch(token -> token.semanticKey().equals(PbsSemanticKind.METHOD.semanticKey()))); + assertTrue(semanticTokens.stream().anyMatch(token -> token.semanticKey().equals(PbsSemanticKind.SERVICE.semanticKey()))); + assertTrue(semanticTokens.stream().anyMatch(token -> token.semanticKey().equals(PbsSemanticKind.HOST.semanticKey()))); + assertTrue(semanticTokens.stream().anyMatch(token -> token.semanticKey().equals(PbsSemanticKind.ENUM.semanticKey()))); } } diff --git a/prometeu-lsp/prometeu-lsp-v1/src/test/java/p/studio/lsp/services/compiler/CompilerLanguageServiceBridgeTest.java b/prometeu-lsp/prometeu-lsp-v1/src/test/java/p/studio/lsp/services/compiler/CompilerLanguageServiceBridgeTest.java index 30d03082..39380c5d 100644 --- a/prometeu-lsp/prometeu-lsp-v1/src/test/java/p/studio/lsp/services/compiler/CompilerLanguageServiceBridgeTest.java +++ b/prometeu-lsp/prometeu-lsp-v1/src/test/java/p/studio/lsp/services/compiler/CompilerLanguageServiceBridgeTest.java @@ -52,10 +52,17 @@ class CompilerLanguageServiceBridgeTest { } } + service Log {} + host Input {} + enum ResultKind { Ok = 1; } + fn main() -> void { const answer: int = 42; let value = new Vec2(); value.length(); + Log.info(); + Input.read(); + let kind: ResultKind; } """); @@ -68,6 +75,9 @@ class CompilerLanguageServiceBridgeTest { assertTrue(semanticTokens.tokens().stream().anyMatch(token -> token.semanticKey().equals("pbs-const"))); assertTrue(semanticTokens.tokens().stream().anyMatch(token -> token.semanticKey().equals("pbs-builtin-type"))); assertTrue(semanticTokens.tokens().stream().anyMatch(token -> token.semanticKey().equals("pbs-constructor"))); + assertTrue(semanticTokens.tokens().stream().anyMatch(token -> token.semanticKey().equals("pbs-service"))); + assertTrue(semanticTokens.tokens().stream().anyMatch(token -> token.semanticKey().equals("pbs-host"))); + assertTrue(semanticTokens.tokens().stream().anyMatch(token -> token.semanticKey().equals("pbs-enum"))); } @Test diff --git a/test-projects/main/.vscode/settings.json b/test-projects/main/.vscode/settings.json index 593300da..1bbfd9cd 100644 --- a/test-projects/main/.vscode/settings.json +++ b/test-projects/main/.vscode/settings.json @@ -36,7 +36,7 @@ "italic": true }, "pbs-service:pbs": { - "foreground": "#c297ff", + "foreground": "#ff8e7a", "bold": true }, "pbs-error:pbs": { -- 2.47.2 From 905d92afe799d445cb83a86a31ac39e0af9ce07d Mon Sep 17 00:00:00 2001 From: bQUARKz Date: Thu, 7 May 2026 14:21:31 +0100 Subject: [PATCH 30/37] Highlight color adjustments --- .../compiler/PBSFrontendHostProjections.java | 1 + .../p/studio/compiler/PBSFrontendThemes.java | 19 +- .../compiler/PBSSemanticTokenProvider.java | 200 ++++- .../studio/compiler/pbs/PbsSemanticKind.java | 1 + .../PbsSemanticPresentationContractTest.java | 66 +- .../CompilerLanguageServiceBridgeTest.java | 20 +- test-projects/main/.vscode/settings.json | 64 +- .../main/assets/.prometeu/cache.json | 784 +++++++++--------- test-projects/main/src/main.pbs | 12 +- 9 files changed, 705 insertions(+), 462 deletions(-) diff --git a/prometeu-compiler/frontends/prometeu-frontend-pbs/src/main/java/p/studio/compiler/PBSFrontendHostProjections.java b/prometeu-compiler/frontends/prometeu-frontend-pbs/src/main/java/p/studio/compiler/PBSFrontendHostProjections.java index b73fec13..068a10ea 100644 --- a/prometeu-compiler/frontends/prometeu-frontend-pbs/src/main/java/p/studio/compiler/PBSFrontendHostProjections.java +++ b/prometeu-compiler/frontends/prometeu-frontend-pbs/src/main/java/p/studio/compiler/PBSFrontendHostProjections.java @@ -39,6 +39,7 @@ public final class PBSFrontendHostProjections { case HOST -> projection(HOST.semanticKey(), "class", "type", "defaultLibrary"); case BUILTIN_TYPE -> projection(BUILTIN_TYPE.semanticKey(), "type", "variable", "defaultLibrary"); case SERVICE -> projection(SERVICE.semanticKey(), "class", "type", "defaultLibrary"); + case ASSET -> projection(ASSET.semanticKey(), "variable", "string", "readonly"); case ERROR -> projection(ERROR.semanticKey(), "enum", "type"); case ENUM -> projection(ENUM.semanticKey(), "enum", "type"); case CALLBACK -> projection(CALLBACK.semanticKey(), "interface", "type"); diff --git a/prometeu-compiler/frontends/prometeu-frontend-pbs/src/main/java/p/studio/compiler/PBSFrontendThemes.java b/prometeu-compiler/frontends/prometeu-frontend-pbs/src/main/java/p/studio/compiler/PBSFrontendThemes.java index 1951d704..da9bc63c 100644 --- a/prometeu-compiler/frontends/prometeu-frontend-pbs/src/main/java/p/studio/compiler/PBSFrontendThemes.java +++ b/prometeu-compiler/frontends/prometeu-frontend-pbs/src/main/java/p/studio/compiler/PBSFrontendThemes.java @@ -20,21 +20,22 @@ public class PBSFrontendThemes { "#f5efff"), List.of( new FrontendTokenStyleSpec("pbs-comment", "#8b949e", true, false, false), - new FrontendTokenStyleSpec("pbs-string", "#7ee787", false, false, false), - new FrontendTokenStyleSpec("pbs-number", "#ffa657", false, false, false), - new FrontendTokenStyleSpec("pbs-literal", "#79c0ff", false, false, false), + new FrontendTokenStyleSpec("pbs-string", "#d8b86a", false, false, false), + new FrontendTokenStyleSpec("pbs-number", "#ff8cc6", false, false, false), + new FrontendTokenStyleSpec("pbs-literal", "#7fb8ff", false, false, false), new FrontendTokenStyleSpec("pbs-lifecycle", "#ff7b72", false, true, false), - new FrontendTokenStyleSpec("pbs-keyword", "#d2a8ff", false, false, false), + new FrontendTokenStyleSpec("pbs-keyword", "#7fb8ff", false, false, false), new FrontendTokenStyleSpec("pbs-operator", "#c9d1d9", false, false, false), new FrontendTokenStyleSpec("pbs-punctuation", "#8b949e", false, false, false), - new FrontendTokenStyleSpec("pbs-function", "#ffa657", false, true, false), - new FrontendTokenStyleSpec("pbs-method", "#ffd580", false, false, false), - new FrontendTokenStyleSpec("pbs-constructor", "#e3b341", false, true, false), - new FrontendTokenStyleSpec("pbs-struct", "#56d4dd", false, false, false), + new FrontendTokenStyleSpec("pbs-function", "#7ee787", false, true, false), + new FrontendTokenStyleSpec("pbs-method", "#7ee787", false, false, false), + new FrontendTokenStyleSpec("pbs-constructor", "#7ee787", false, true, false), + new FrontendTokenStyleSpec("pbs-struct", "#56d4dd", true, false, false), new FrontendTokenStyleSpec("pbs-contract", "#79c0ff", false, false, true), new FrontendTokenStyleSpec("pbs-host", "#c297ff", false, false, false), - new FrontendTokenStyleSpec("pbs-builtin-type", "#7ee787", true, false, false), + new FrontendTokenStyleSpec("pbs-builtin-type", "#56d4dd", false, false, false), new FrontendTokenStyleSpec("pbs-service", "#ff8e7a", false, true, false), + new FrontendTokenStyleSpec("pbs-asset", "#c297ff", false, false, false), new FrontendTokenStyleSpec("pbs-error", "#ff7b72", false, false, true), new FrontendTokenStyleSpec("pbs-enum", "#56d4dd", false, true, false), new FrontendTokenStyleSpec("pbs-callback", "#ffb3e6", false, false, false), diff --git a/prometeu-compiler/frontends/prometeu-frontend-pbs/src/main/java/p/studio/compiler/PBSSemanticTokenProvider.java b/prometeu-compiler/frontends/prometeu-frontend-pbs/src/main/java/p/studio/compiler/PBSSemanticTokenProvider.java index 8e177534..164841a0 100644 --- a/prometeu-compiler/frontends/prometeu-frontend-pbs/src/main/java/p/studio/compiler/PBSSemanticTokenProvider.java +++ b/prometeu-compiler/frontends/prometeu-frontend-pbs/src/main/java/p/studio/compiler/PBSSemanticTokenProvider.java @@ -2,33 +2,44 @@ package p.studio.compiler; import p.studio.compiler.models.FrontendSemanticToken; import p.studio.compiler.models.FrontendSemanticTokenProvider; +import p.studio.compiler.pbs.ast.PbsAst; import p.studio.compiler.pbs.PbsSemanticKind; import p.studio.compiler.pbs.lexer.PbsLexer; import p.studio.compiler.pbs.lexer.PbsToken; import p.studio.compiler.pbs.lexer.PbsTokenKind; +import p.studio.compiler.pbs.parser.PbsBarrelParser; +import p.studio.compiler.pbs.parser.PbsParser; +import p.studio.compiler.pbs.stdlib.ResourceStdlibEnvironmentResolver; +import p.studio.compiler.pbs.stdlib.StdlibModuleSource; import p.studio.compiler.source.diagnostics.DiagnosticSink; import p.studio.compiler.source.identifiers.FileId; import p.studio.utilities.structures.ReadOnlyList; import java.util.ArrayList; +import java.util.EnumMap; import java.util.HashMap; +import java.util.HashSet; import java.util.List; import java.util.Map; import java.util.Set; public final class PBSSemanticTokenProvider implements FrontendSemanticTokenProvider { private static final Set BUILTIN_TYPE_NAMES = Set.of("int", "float", "bool", "string", "i32", "i64", "f32", "f64"); + private static final int DEFAULT_STDLIB_VERSION = 1; + private static final ResourceStdlibEnvironmentResolver STDLIB_RESOLVER = new ResourceStdlibEnvironmentResolver(); + private static final Map DECLARATION_KINDS = declarationKinds(); @Override public List tokenize(final String documentText) { final String effectiveText = documentText == null ? "" : documentText; final ReadOnlyList tokens = PbsLexer.lex(effectiveText, FileId.none(), DiagnosticSink.empty()); final Map declaredKindsByName = collectDeclaredKinds(tokens); + final Set assetReferenceTokenIndexes = collectAssetReferenceTokenIndexes(tokens); final ArrayList semanticTokens = new ArrayList<>(); for (int index = 0; index < tokens.size(); index += 1) { final PbsToken token = tokens.get(index); - final PbsSemanticKind semanticKind = classifyToken(tokens, index, declaredKindsByName); + final PbsSemanticKind semanticKind = classifyToken(tokens, index, declaredKindsByName, assetReferenceTokenIndexes); if (semanticKind == null) { continue; } @@ -41,13 +52,17 @@ public final class PBSSemanticTokenProvider implements FrontendSemanticTokenProv private PbsSemanticKind classifyToken( final ReadOnlyList tokens, final int index, - final Map declaredKindsByName) { + final Map declaredKindsByName, + final Set assetReferenceTokenIndexes) { final PbsToken token = tokens.get(index); final PbsSemanticKind lexicalKind = PbsSemanticKind.forToken(token); if (lexicalKind != null) { return lexicalKind; } if (token.kind() == PbsTokenKind.IDENTIFIER) { + if (assetReferenceTokenIndexes.contains(index)) { + return PbsSemanticKind.ASSET; + } if (isLifecycleToken(tokens, index, token)) { return PbsSemanticKind.LIFECYCLE; } @@ -63,6 +78,7 @@ public final class PBSSemanticTokenProvider implements FrontendSemanticTokenProv final Map declaredKindsByName) { final PbsTokenKind previousKind = previousSignificantKind(tokens, index); final PbsTokenKind nextKind = nextSignificantKind(tokens, index); + final boolean typeReferenceContext = isTypeReferenceContext(previousKind); if (previousKind == PbsTokenKind.STRUCT) { return PbsSemanticKind.STRUCT; @@ -101,7 +117,7 @@ public final class PBSSemanticTokenProvider implements FrontendSemanticTokenProv } if (nextKind == PbsTokenKind.DOT || previousKind == PbsTokenKind.NEW - || isTypeReferenceContext(previousKind, token.lexeme())) { + || typeReferenceContext) { return declaredKind; } } @@ -111,7 +127,7 @@ public final class PBSSemanticTokenProvider implements FrontendSemanticTokenProv if (nextKind == PbsTokenKind.LEFT_PAREN) { return PbsSemanticKind.FUNCTION; } - if (isTypeReferenceContext(previousKind, token.lexeme())) { + if (typeReferenceContext && BUILTIN_TYPE_NAMES.contains(token.lexeme())) { return PbsSemanticKind.BUILTIN_TYPE; } return PbsSemanticKind.IDENTIFIER; @@ -131,28 +147,163 @@ public final class PBSSemanticTokenProvider implements FrontendSemanticTokenProv } declaredKindsByName.put(nextToken.lexeme(), declarationKind); } + declaredKindsByName.putAll(collectStdlibImportedKinds(tokens)); return Map.copyOf(declaredKindsByName); } + private Set collectAssetReferenceTokenIndexes(final ReadOnlyList tokens) { + final Set indexes = new HashSet<>(); + for (int index = 0; index < tokens.size(); index += 1) { + final PbsToken token = tokens.get(index); + if (token.kind() != PbsTokenKind.IDENTIFIER || !"assets".equals(token.lexeme())) { + continue; + } + final Integer firstDotIndex = nextSignificantIndex(tokens, index); + if (firstDotIndex == null || tokens.get(firstDotIndex).kind() != PbsTokenKind.DOT) { + continue; + } + + indexes.add(index); + Integer cursor = firstDotIndex; + while (cursor != null && tokens.get(cursor).kind() == PbsTokenKind.DOT) { + final Integer memberIndex = nextSignificantIndex(tokens, cursor); + if (memberIndex == null || tokens.get(memberIndex).kind() != PbsTokenKind.IDENTIFIER) { + break; + } + indexes.add(memberIndex); + cursor = nextSignificantIndex(tokens, memberIndex); + } + } + return Set.copyOf(indexes); + } + private PbsSemanticKind declarationKind(final PbsTokenKind kind) { - return switch (kind) { - case STRUCT -> PbsSemanticKind.STRUCT; - case CONTRACT -> PbsSemanticKind.CONTRACT; - case HOST -> PbsSemanticKind.HOST; - case SERVICE -> PbsSemanticKind.SERVICE; - case ENUM, ERROR -> PbsSemanticKind.ENUM; - case CALLBACK -> PbsSemanticKind.CALLBACK; - case GLOBAL -> PbsSemanticKind.GLOBAL; - case CONST -> PbsSemanticKind.CONST; - case CTOR -> PbsSemanticKind.CONSTRUCTOR; - case BUILTIN -> PbsSemanticKind.BUILTIN_TYPE; - default -> null; + return DECLARATION_KINDS.get(kind); + } + + private Map collectStdlibImportedKinds(final ReadOnlyList tokens) { + final DiagnosticSink diagnostics = DiagnosticSink.empty(); + final PbsAst.File file = PbsParser.parse(tokens, FileId.none(), diagnostics); + final Map importedKindsByLocalName = new HashMap<>(); + for (final PbsAst.ImportDecl importDecl : file.imports()) { + if (importDecl.items().isEmpty()) { + continue; + } + final Map exportedKinds = resolveStdlibExportKinds(importDecl.moduleRef()); + if (exportedKinds.isEmpty()) { + continue; + } + for (final Map.Entry entry : exportedKinds.entrySet()) { + if (entry.getValue() == PbsSemanticKind.BUILTIN_TYPE) { + importedKindsByLocalName.put(entry.getKey(), entry.getValue()); + } + } + for (final PbsAst.ImportItem item : importDecl.items()) { + final PbsSemanticKind semanticKind = exportedKinds.get(item.name()); + if (semanticKind == null) { + continue; + } + importedKindsByLocalName.put(item.alias() == null ? item.name() : item.alias(), semanticKind); + } + } + return importedKindsByLocalName; + } + + private Map resolveStdlibExportKinds(final PbsAst.ModuleRef moduleRef) { + final var stdlibEnvironment = STDLIB_RESOLVER.resolve(DEFAULT_STDLIB_VERSION); + return stdlibEnvironment.resolveModule(moduleRef.project(), moduleRef.pathSegments()) + .map(this::parseStdlibVisibleKinds) + .orElseGet(Map::of); + } + + private Map parseStdlibVisibleKinds(final StdlibModuleSource moduleSource) { + final Map visibleKinds = new HashMap<>(parseBarrelExportKinds(moduleSource.barrelSource())); + for (final StdlibModuleSource.SourceFile sourceFile : moduleSource.sourceFiles()) { + visibleKinds.putAll(parseBuiltinTypeKinds(sourceFile.source())); + } + return visibleKinds; + } + + private Map parseBarrelExportKinds(final String barrelSource) { + final ReadOnlyList barrelTokens = PbsLexer.lex(barrelSource, FileId.none(), DiagnosticSink.empty()); + final PbsAst.BarrelFile barrelFile = PbsBarrelParser.parse(barrelTokens, FileId.none(), DiagnosticSink.empty()); + final Map exportedKinds = new HashMap<>(); + for (final PbsAst.BarrelItem item : barrelFile.items()) { + final PbsSemanticKind semanticKind = semanticKindForBarrelItem(item); + if (semanticKind == null) { + continue; + } + if (item instanceof PbsAst.BarrelStructItem structItem && structItem.visibility() == PbsAst.Visibility.PUB) { + exportedKinds.put(structItem.name(), semanticKind); + } else if (item instanceof PbsAst.BarrelContractItem contractItem && contractItem.visibility() == PbsAst.Visibility.PUB) { + exportedKinds.put(contractItem.name(), semanticKind); + } else if (item instanceof PbsAst.BarrelHostItem hostItem && hostItem.visibility() == PbsAst.Visibility.PUB) { + exportedKinds.put(hostItem.name(), semanticKind); + } else if (item instanceof PbsAst.BarrelErrorItem errorItem && errorItem.visibility() == PbsAst.Visibility.PUB) { + exportedKinds.put(errorItem.name(), semanticKind); + } else if (item instanceof PbsAst.BarrelEnumItem enumItem && enumItem.visibility() == PbsAst.Visibility.PUB) { + exportedKinds.put(enumItem.name(), semanticKind); + } else if (item instanceof PbsAst.BarrelServiceItem serviceItem && serviceItem.visibility() == PbsAst.Visibility.PUB) { + exportedKinds.put(serviceItem.name(), semanticKind); + } else if (item instanceof PbsAst.BarrelGlobalItem globalItem && globalItem.visibility() == PbsAst.Visibility.PUB) { + exportedKinds.put(globalItem.name(), semanticKind); + } else if (item instanceof PbsAst.BarrelConstItem constItem && constItem.visibility() == PbsAst.Visibility.PUB) { + exportedKinds.put(constItem.name(), semanticKind); + } else if (item instanceof PbsAst.BarrelCallbackItem callbackItem && callbackItem.visibility() == PbsAst.Visibility.PUB) { + exportedKinds.put(callbackItem.name(), semanticKind); + } + } + return exportedKinds; + } + + private Map parseBuiltinTypeKinds(final String source) { + final ReadOnlyList sourceTokens = PbsLexer.lex(source, FileId.none(), DiagnosticSink.empty()); + final PbsAst.File file = PbsParser.parse( + sourceTokens, + FileId.none(), + DiagnosticSink.empty(), + PbsParser.ParseMode.INTERFACE_MODULE); + final Map builtinKinds = new HashMap<>(); + for (final PbsAst.TopDecl topDecl : file.topDecls()) { + if (topDecl instanceof PbsAst.BuiltinTypeDecl builtinTypeDecl) { + builtinKinds.put(builtinTypeDecl.name(), PbsSemanticKind.BUILTIN_TYPE); + } + } + return builtinKinds; + } + + private PbsSemanticKind semanticKindForBarrelItem(final PbsAst.BarrelItem item) { + return switch (item) { + case PbsAst.BarrelStructItem ignored -> PbsSemanticKind.STRUCT; + case PbsAst.BarrelContractItem ignored -> PbsSemanticKind.CONTRACT; + case PbsAst.BarrelHostItem ignored -> PbsSemanticKind.HOST; + case PbsAst.BarrelErrorItem ignored -> PbsSemanticKind.ENUM; + case PbsAst.BarrelEnumItem ignored -> PbsSemanticKind.ENUM; + case PbsAst.BarrelServiceItem ignored -> PbsSemanticKind.SERVICE; + case PbsAst.BarrelGlobalItem ignored -> PbsSemanticKind.GLOBAL; + case PbsAst.BarrelConstItem ignored -> PbsSemanticKind.CONST; + case PbsAst.BarrelCallbackItem ignored -> PbsSemanticKind.CALLBACK; + case PbsAst.BarrelFunctionItem ignored -> null; }; } - private boolean isTypeReferenceContext( - final PbsTokenKind previousKind, - final String lexeme) { + private static Map declarationKinds() { + final Map kinds = new EnumMap<>(PbsTokenKind.class); + kinds.put(PbsTokenKind.STRUCT, PbsSemanticKind.STRUCT); + kinds.put(PbsTokenKind.CONTRACT, PbsSemanticKind.CONTRACT); + kinds.put(PbsTokenKind.HOST, PbsSemanticKind.HOST); + kinds.put(PbsTokenKind.SERVICE, PbsSemanticKind.SERVICE); + kinds.put(PbsTokenKind.ENUM, PbsSemanticKind.ENUM); + kinds.put(PbsTokenKind.ERROR, PbsSemanticKind.ENUM); + kinds.put(PbsTokenKind.CALLBACK, PbsSemanticKind.CALLBACK); + kinds.put(PbsTokenKind.GLOBAL, PbsSemanticKind.GLOBAL); + kinds.put(PbsTokenKind.CONST, PbsSemanticKind.CONST); + kinds.put(PbsTokenKind.CTOR, PbsSemanticKind.CONSTRUCTOR); + kinds.put(PbsTokenKind.BUILTIN, PbsSemanticKind.BUILTIN_TYPE); + return Map.copyOf(kinds); + } + + private boolean isTypeReferenceContext(final PbsTokenKind previousKind) { if (previousKind == null) { return false; } @@ -162,7 +313,7 @@ public final class PBSSemanticTokenProvider implements FrontendSemanticTokenProv && previousKind != PbsTokenKind.IMPLEMENTS) { return false; } - return BUILTIN_TYPE_NAMES.contains(lexeme); + return true; } private PbsTokenKind previousSignificantKind( @@ -181,12 +332,19 @@ public final class PBSSemanticTokenProvider implements FrontendSemanticTokenProv private PbsTokenKind nextSignificantKind( final ReadOnlyList tokens, final int index) { + final Integer cursor = nextSignificantIndex(tokens, index); + return cursor == null ? null : tokens.get(cursor).kind(); + } + + private Integer nextSignificantIndex( + final ReadOnlyList tokens, + final int index) { for (int cursor = index + 1; cursor < tokens.size(); cursor += 1) { final PbsTokenKind kind = tokens.get(cursor).kind(); if (kind == PbsTokenKind.COMMENT || kind == PbsTokenKind.EOF) { continue; } - return kind; + return cursor; } return null; } diff --git a/prometeu-compiler/frontends/prometeu-frontend-pbs/src/main/java/p/studio/compiler/pbs/PbsSemanticKind.java b/prometeu-compiler/frontends/prometeu-frontend-pbs/src/main/java/p/studio/compiler/pbs/PbsSemanticKind.java index bae8c491..3d72d9a6 100644 --- a/prometeu-compiler/frontends/prometeu-frontend-pbs/src/main/java/p/studio/compiler/pbs/PbsSemanticKind.java +++ b/prometeu-compiler/frontends/prometeu-frontend-pbs/src/main/java/p/studio/compiler/pbs/PbsSemanticKind.java @@ -22,6 +22,7 @@ public enum PbsSemanticKind { HOST("pbs-host"), BUILTIN_TYPE("pbs-builtin-type"), SERVICE("pbs-service"), + ASSET("pbs-asset"), ERROR("pbs-error"), ENUM("pbs-enum"), CALLBACK("pbs-callback"), diff --git a/prometeu-compiler/frontends/prometeu-frontend-pbs/src/test/java/p/studio/compiler/pbs/PbsSemanticPresentationContractTest.java b/prometeu-compiler/frontends/prometeu-frontend-pbs/src/test/java/p/studio/compiler/pbs/PbsSemanticPresentationContractTest.java index ff28d4ae..1d62614f 100644 --- a/prometeu-compiler/frontends/prometeu-frontend-pbs/src/test/java/p/studio/compiler/pbs/PbsSemanticPresentationContractTest.java +++ b/prometeu-compiler/frontends/prometeu-frontend-pbs/src/test/java/p/studio/compiler/pbs/PbsSemanticPresentationContractTest.java @@ -23,9 +23,19 @@ final class PbsSemanticPresentationContractTest { assertEquals(1, presentation.themes().size()); assertEquals("PBS Default", presentation.defaultTheme().displayName()); assertEquals("#d9e2ec", presentation.defaultTheme().editorPalette().baseForeground()); - assertEquals("#d2a8ff", presentation.defaultTheme().requireTokenStyle("pbs-keyword").foreground()); + assertEquals("#7fb8ff", presentation.defaultTheme().requireTokenStyle("pbs-keyword").foreground()); + assertEquals("#d8b86a", presentation.defaultTheme().requireTokenStyle("pbs-string").foreground()); + assertEquals("#ff8cc6", presentation.defaultTheme().requireTokenStyle("pbs-number").foreground()); + assertEquals("#7fb8ff", presentation.defaultTheme().requireTokenStyle("pbs-literal").foreground()); + assertEquals("#7ee787", presentation.defaultTheme().requireTokenStyle("pbs-function").foreground()); + assertEquals("#7ee787", presentation.defaultTheme().requireTokenStyle("pbs-method").foreground()); + assertEquals("#7ee787", presentation.defaultTheme().requireTokenStyle("pbs-constructor").foreground()); + assertEquals("#56d4dd", presentation.defaultTheme().requireTokenStyle("pbs-struct").foreground()); + assertTrue(presentation.defaultTheme().requireTokenStyle("pbs-struct").italic()); + assertEquals("#56d4dd", presentation.defaultTheme().requireTokenStyle("pbs-builtin-type").foreground()); + assertFalse(presentation.defaultTheme().requireTokenStyle("pbs-builtin-type").italic()); assertEquals("#ff8e7a", presentation.defaultTheme().requireTokenStyle("pbs-service").foreground()); - assertTrue(presentation.defaultTheme().requireTokenStyle("pbs-builtin-type").italic()); + assertEquals("#c297ff", presentation.defaultTheme().requireTokenStyle("pbs-asset").foreground()); assertTrue(presentation.defaultTheme().requireTokenStyle("pbs-comment").italic()); assertEquals(PBSFrontendHostProjections.VSCODE_HOST_ID, presentation.requireHostProjection("vscode").hostId()); } @@ -50,6 +60,7 @@ final class PbsSemanticPresentationContractTest { vscodeProjection.tokenProjections().stream().map(tokenProjection -> tokenProjection.semanticKey()).toList()); assertEquals("keyword", vscodeProjection.requireProjection(PbsSemanticKind.KEYWORD.semanticKey()).hostTokenType()); assertEquals("type", vscodeProjection.requireProjection(PbsSemanticKind.STRUCT.semanticKey()).fallbackTokenType()); + assertEquals("variable", vscodeProjection.requireProjection(PbsSemanticKind.ASSET.semanticKey()).hostTokenType()); assertEquals( java.util.List.of("readonly"), vscodeProjection.requireProjection(PbsSemanticKind.GLOBAL.semanticKey()).hostTokenModifiers()); @@ -73,7 +84,7 @@ final class PbsSemanticPresentationContractTest { } """); - assertTrue(semanticTokens.stream().anyMatch(token -> token.semanticKey().equals(PbsSemanticKind.STRUCT.semanticKey()))); + assertTrue(semanticTokens.stream().anyMatch(token -> token.semanticKey().equals(PbsSemanticKind.BUILTIN_TYPE.semanticKey()))); assertTrue(semanticTokens.stream().anyMatch(token -> token.semanticKey().equals(PbsSemanticKind.FUNCTION.semanticKey()))); assertTrue(semanticTokens.stream().anyMatch(token -> token.semanticKey().equals(PbsSemanticKind.CONST.semanticKey()))); assertTrue(semanticTokens.stream().anyMatch(token -> token.semanticKey().equals(PbsSemanticKind.BUILTIN_TYPE.semanticKey()))); @@ -83,4 +94,53 @@ final class PbsSemanticPresentationContractTest { assertTrue(semanticTokens.stream().anyMatch(token -> token.semanticKey().equals(PbsSemanticKind.HOST.semanticKey()))); assertTrue(semanticTokens.stream().anyMatch(token -> token.semanticKey().equals(PbsSemanticKind.ENUM.semanticKey()))); } + + @Test + void shouldClassifyStdlibImportsUsingTheirPublishedBarrelKinds() { + final List semanticTokens = PBSDefinitions.PBS.getSemanticTokenProvider().tokenize(""" + import { Log } from @sdk:log; + import { Composer } from @sdk:composer; + import { Color as Paint } from @core:color; + + fn main() -> void { + Log.info("hello"); + Composer.emit_sprite(0, 0, 0, 0, 0, 0, false, false, 0); + let paint: Paint; + } + """); + + assertTrue(semanticTokens.stream().anyMatch(token -> token.semanticKey().equals(PbsSemanticKind.SERVICE.semanticKey()))); + assertTrue(semanticTokens.stream().anyMatch(token -> token.semanticKey().equals(PbsSemanticKind.BUILTIN_TYPE.semanticKey()))); + } + + @Test + void shouldClassifyAssetRootedAliasesUsingDedicatedSemanticKind() { + final List semanticTokens = PBSDefinitions.PBS.getSemanticTokenProvider().tokenize(""" + import { Assets } from @sdk:asset; + + fn main() -> void { + Assets.load(assets.ui.atlas2, 3); + } + """); + + final long assetTokenCount = semanticTokens.stream() + .filter(token -> token.semanticKey().equals(PbsSemanticKind.ASSET.semanticKey())) + .count(); + + assertEquals(3, assetTokenCount); + } + + @Test + void shouldClassifyBuiltinTypesExposedByImportedStdlibModules() { + final List semanticTokens = PBSDefinitions.PBS.getSemanticTokenProvider().tokenize(""" + import { Input } from @sdk:input; + + fn main() -> void { + let touch : InputTouch = Input.touch(); + let pad : InputPad = Input.pad(); + } + """); + + assertTrue(semanticTokens.stream().filter(token -> token.semanticKey().equals(PbsSemanticKind.BUILTIN_TYPE.semanticKey())).count() >= 2); + } } diff --git a/prometeu-lsp/prometeu-lsp-v1/src/test/java/p/studio/lsp/services/compiler/CompilerLanguageServiceBridgeTest.java b/prometeu-lsp/prometeu-lsp-v1/src/test/java/p/studio/lsp/services/compiler/CompilerLanguageServiceBridgeTest.java index 39380c5d..87f49fbb 100644 --- a/prometeu-lsp/prometeu-lsp-v1/src/test/java/p/studio/lsp/services/compiler/CompilerLanguageServiceBridgeTest.java +++ b/prometeu-lsp/prometeu-lsp-v1/src/test/java/p/studio/lsp/services/compiler/CompilerLanguageServiceBridgeTest.java @@ -80,6 +80,24 @@ class CompilerLanguageServiceBridgeTest { assertTrue(semanticTokens.tokens().stream().anyMatch(token -> token.semanticKey().equals("pbs-enum"))); } + @Test + void semanticTokensClassifyBuiltinTypesExposedByImportedStdlibModules() { + final CompilerLanguageServiceBridge bridge = new CompilerLanguageServiceBridge(); + + final var semanticTokens = bridge.semanticTokens( + new LspProjectContext("main", "pbs", Path.of(".")), + Path.of("demo.pbs").toUri().toString(), + """ + import { Input } from @sdk:input; + + fn main() -> void { + let touch : InputTouch = Input.touch(); + } + """); + + assertTrue(semanticTokens.tokens().stream().anyMatch(token -> token.semanticKey().equals("pbs-builtin-type"))); + } + @Test void describeServerPublishesFrontendVisualThemes() { final CompilerLanguageServiceBridge bridge = new CompilerLanguageServiceBridge(); @@ -98,7 +116,7 @@ class CompilerLanguageServiceBridgeTest { assertEquals("#d9e2ec", description.visualThemes().getFirst().editorPalette().baseForeground()); assertTrue(description.visualThemes().getFirst().tokenStyles().stream() .anyMatch(tokenStyle -> tokenStyle.semanticKey().equals("pbs-keyword") - && tokenStyle.foreground().equals("#d2a8ff"))); + && tokenStyle.foreground().equals("#7fb8ff"))); } private Path findRepoRoot(final Path start) { diff --git a/test-projects/main/.vscode/settings.json b/test-projects/main/.vscode/settings.json index 1bbfd9cd..57fd1504 100644 --- a/test-projects/main/.vscode/settings.json +++ b/test-projects/main/.vscode/settings.json @@ -6,35 +6,35 @@ "foreground": "#8b949e", "italic": true }, - "pbs-string:pbs": "#7ee787", - "pbs-number:pbs": "#ffa657", - "pbs-literal:pbs": "#79c0ff", + "pbs-string:pbs": "#d8b86a", + "pbs-number:pbs": "#ff8cc6", + "pbs-literal:pbs": "#7fb8ff", "pbs-lifecycle:pbs": { "foreground": "#ff7b72", "bold": true }, - "pbs-keyword:pbs": "#d2a8ff", + "pbs-keyword:pbs": "#7fb8ff", "pbs-operator:pbs": "#c9d1d9", "pbs-punctuation:pbs": "#8b949e", "pbs-function:pbs": { - "foreground": "#ffa657", + "foreground": "#7ee787", "bold": true }, - "pbs-method:pbs": "#ffd580", + "pbs-method:pbs": "#7ee787", "pbs-constructor:pbs": { - "foreground": "#e3b341", + "foreground": "#7ee787", "bold": true }, - "pbs-struct:pbs": "#56d4dd", + "pbs-struct:pbs": { + "foreground": "#56d4dd", + "italic": true + }, "pbs-contract:pbs": { "foreground": "#79c0ff", "underline": true }, "pbs-host:pbs": "#c297ff", - "pbs-builtin-type:pbs": { - "foreground": "#7ee787", - "italic": true - }, + "pbs-builtin-type:pbs": "#56d4dd", "pbs-service:pbs": { "foreground": "#ff8e7a", "bold": true @@ -62,10 +62,10 @@ "foreground": "#8b949e", "italic": true }, - "string:pbs": "#7ee787", - "number:pbs": "#ffa657", - "enumMember:pbs": "#79c0ff", - "variable:pbs": "#79c0ff", + "string:pbs": "#d8b86a", + "number:pbs": "#ff8cc6", + "enumMember:pbs": "#7fb8ff", + "variable:pbs": "#7fb8ff", "function.async:pbs": { "foreground": "#ff7b72", "bold": true @@ -74,41 +74,43 @@ "foreground": "#ff7b72", "bold": true }, - "keyword:pbs": "#d2a8ff", + "keyword:pbs": "#7fb8ff", "operator:pbs": "#c9d1d9", "function:pbs": { - "foreground": "#ffa657", + "foreground": "#7ee787", "bold": true }, - "method:pbs": "#ffd580", + "method:pbs": "#7ee787", "class.declaration:pbs": { - "foreground": "#e3b341", + "foreground": "#7ee787", "bold": true }, "type.declaration:pbs": { - "foreground": "#e3b341", + "foreground": "#7ee787", "bold": true }, - "struct:pbs": "#56d4dd", - "type:pbs": "#56d4dd", + "struct:pbs": { + "foreground": "#56d4dd", + "italic": true + }, + "type:pbs": { + "foreground": "#56d4dd", + "italic": true + }, "interface:pbs": { "foreground": "#79c0ff", "underline": true }, "class.defaultLibrary:pbs": "#c297ff", "type.defaultLibrary:pbs": "#c297ff", - "variable.defaultLibrary:pbs": { - "foreground": "#7ee787", - "italic": true - }, + "variable.defaultLibrary:pbs": "#56d4dd", "enum:pbs": { "foreground": "#ff7b72", "underline": true }, - "variable.readonly:pbs": { - "foreground": "#f778ba", - "italic": true - } + "variable.readonly:pbs": "#c297ff", + "pbs-asset:pbs": "#c297ff", + "string.readonly:pbs": "#c297ff" } }, "workbench.colorCustomizations": { diff --git a/test-projects/main/assets/.prometeu/cache.json b/test-projects/main/assets/.prometeu/cache.json index 7d30e3eb..0a8c0fad 100644 --- a/test-projects/main/assets/.prometeu/cache.json +++ b/test-projects/main/assets/.prometeu/cache.json @@ -24,14 +24,14 @@ "last_modified" : 1774359772403, "fingerprint" : "eeb7cc665386299403b7be1c272375d5077f3647c587f8033aa8c9275f840562", "metadata" : { - "palette" : { - "originalArgb8888" : [ -265674 ], - "convertedRgb565" : [ -122 ] - }, "tile" : { "width" : 32, "height" : 32, "paletteIndices" : "AQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAAAAAAAAAAABAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEAAAAAAAAAAAEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQAAAAAAAAAAAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAAAAAAAAAAABAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEAAAAAAAAAAAEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQAAAAAAAAAAAQEBAQEBAQEBAQEBAAAAAAAAAAAAAAAAAAAAAAAAAAABAQEBAQEBAQEBAQEAAAAAAAAAAAAAAAAAAAAAAAAAAAEBAQEBAQEBAQEBAQAAAAAAAAAAAAAAAAAAAAAAAAAAAQEBAQEBAQEBAQEBAAAAAAAAAAAAAAAAAAAAAAAAAAABAQEBAQEBAQEBAQEAAAAAAAAAAAAAAAAAAAAAAAAAAAEBAQEBAQEBAQEBAQAAAAAAAAAAAAAAAAAAAAAAAAAAAQEBAQEBAQEBAQEBAAAAAAAAAAAAAAAAAAAAAAAAAAABAQEBAQEBAQEBAQEAAAAAAAAAAAAAAAAAAAAAAAAAAAEBAQEBAQEBAQEBAQAAAAAAAAAAAAAAAAAAAQEBAQEBAQEBAQEBAQEBAQEBAAAAAAAAAAAAAAAAAAABAQEBAQEBAQEBAQEBAQEBAQEAAAAAAAAAAAAAAAAAAAEBAQEBAQEBAQEBAQEBAQEBAQAAAAAAAAAAAAAAAAAAAQEBAQEBAQEBAQEBAAAAAAAAAAAAAAAAAAAAAAAAAAABAQEBAQEBAQEBAQEAAAAAAAAAAAAAAAAAAAAAAAAAAAEBAQEBAQEBAQEBAQAAAAAAAAAAAAAAAAAAAQEBAQEBAQEBAQEBAQEBAQEBAAAAAAAAAAAAAAAAAAABAQEBAQEBAQEBAQEBAQEBAQEAAAAAAAAAAAAAAAAAAAEBAQEBAQEBAQEBAQEBAQEBAQAAAAAAAAAAAAAAAAAAAQEBAQEBAQEBAQEBAQEBAQEBAAAAAAAAAAAAAAAAAAABAQEBAQEBAQEBAQEBAQEBAQEAAAAAAAAAAAAAAAAAAAEBAQEBAQEBAQEBAQ==" + }, + "palette" : { + "originalArgb8888" : [ -265674 ], + "convertedRgb565" : [ -122 ] } }, "diagnostics" : [ ] @@ -42,14 +42,14 @@ "last_modified" : 1774359772405, "fingerprint" : "eeb7cc665386299403b7be1c272375d5077f3647c587f8033aa8c9275f840562", "metadata" : { - "palette" : { - "originalArgb8888" : [ -265674 ], - "convertedRgb565" : [ -122 ] - }, "tile" : { "width" : 32, "height" : 32, "paletteIndices" : "AQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAAAAAAAAAAABAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEAAAAAAAAAAAEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQAAAAAAAAAAAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAAAAAAAAAAABAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEAAAAAAAAAAAEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQAAAAAAAAAAAQEBAQEBAQEBAQEBAAAAAAAAAAAAAAAAAAAAAAAAAAABAQEBAQEBAQEBAQEAAAAAAAAAAAAAAAAAAAAAAAAAAAEBAQEBAQEBAQEBAQAAAAAAAAAAAAAAAAAAAAAAAAAAAQEBAQEBAQEBAQEBAAAAAAAAAAAAAAAAAAAAAAAAAAABAQEBAQEBAQEBAQEAAAAAAAAAAAAAAAAAAAAAAAAAAAEBAQEBAQEBAQEBAQAAAAAAAAAAAAAAAAAAAAAAAAAAAQEBAQEBAQEBAQEBAAAAAAAAAAAAAAAAAAAAAAAAAAABAQEBAQEBAQEBAQEAAAAAAAAAAAAAAAAAAAAAAAAAAAEBAQEBAQEBAQEBAQAAAAAAAAAAAAAAAAAAAQEBAQEBAQEBAQEBAQEBAQEBAAAAAAAAAAAAAAAAAAABAQEBAQEBAQEBAQEBAQEBAQEAAAAAAAAAAAAAAAAAAAEBAQEBAQEBAQEBAQEBAQEBAQAAAAAAAAAAAAAAAAAAAQEBAQEBAQEBAQEBAAAAAAAAAAAAAAAAAAAAAAAAAAABAQEBAQEBAQEBAQEAAAAAAAAAAAAAAAAAAAAAAAAAAAEBAQEBAQEBAQEBAQAAAAAAAAAAAAAAAAAAAQEBAQEBAQEBAQEBAQEBAQEBAAAAAAAAAAAAAAAAAAABAQEBAQEBAQEBAQEBAQEBAQEAAAAAAAAAAAAAAAAAAAEBAQEBAQEBAQEBAQEBAQEBAQAAAAAAAAAAAAAAAAAAAQEBAQEBAQEBAQEBAQEBAQEBAAAAAAAAAAAAAAAAAAABAQEBAQEBAQEBAQEBAQEBAQEAAAAAAAAAAAAAAAAAAAEBAQEBAQEBAQEBAQ==" + }, + "palette" : { + "originalArgb8888" : [ -265674 ], + "convertedRgb565" : [ -122 ] } }, "diagnostics" : [ ] @@ -60,14 +60,14 @@ "last_modified" : 1774359772406, "fingerprint" : "eeb7cc665386299403b7be1c272375d5077f3647c587f8033aa8c9275f840562", "metadata" : { - "palette" : { - "originalArgb8888" : [ -265674 ], - "convertedRgb565" : [ -122 ] - }, "tile" : { "width" : 32, "height" : 32, "paletteIndices" : "AQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAAAAAAAAAAABAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEAAAAAAAAAAAEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQAAAAAAAAAAAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAAAAAAAAAAABAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEAAAAAAAAAAAEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQAAAAAAAAAAAQEBAQEBAQEBAQEBAAAAAAAAAAAAAAAAAAAAAAAAAAABAQEBAQEBAQEBAQEAAAAAAAAAAAAAAAAAAAAAAAAAAAEBAQEBAQEBAQEBAQAAAAAAAAAAAAAAAAAAAAAAAAAAAQEBAQEBAQEBAQEBAAAAAAAAAAAAAAAAAAAAAAAAAAABAQEBAQEBAQEBAQEAAAAAAAAAAAAAAAAAAAAAAAAAAAEBAQEBAQEBAQEBAQAAAAAAAAAAAAAAAAAAAAAAAAAAAQEBAQEBAQEBAQEBAAAAAAAAAAAAAAAAAAAAAAAAAAABAQEBAQEBAQEBAQEAAAAAAAAAAAAAAAAAAAAAAAAAAAEBAQEBAQEBAQEBAQAAAAAAAAAAAAAAAAAAAQEBAQEBAQEBAQEBAQEBAQEBAAAAAAAAAAAAAAAAAAABAQEBAQEBAQEBAQEBAQEBAQEAAAAAAAAAAAAAAAAAAAEBAQEBAQEBAQEBAQEBAQEBAQAAAAAAAAAAAAAAAAAAAQEBAQEBAQEBAQEBAAAAAAAAAAAAAAAAAAAAAAAAAAABAQEBAQEBAQEBAQEAAAAAAAAAAAAAAAAAAAAAAAAAAAEBAQEBAQEBAQEBAQAAAAAAAAAAAAAAAAAAAQEBAQEBAQEBAQEBAQEBAQEBAAAAAAAAAAAAAAAAAAABAQEBAQEBAQEBAQEBAQEBAQEAAAAAAAAAAAAAAAAAAAEBAQEBAQEBAQEBAQEBAQEBAQAAAAAAAAAAAAAAAAAAAQEBAQEBAQEBAQEBAQEBAQEBAAAAAAAAAAAAAAAAAAABAQEBAQEBAQEBAQEBAQEBAQEAAAAAAAAAAAAAAAAAAAEBAQEBAQEBAQEBAQ==" + }, + "palette" : { + "originalArgb8888" : [ -265674 ], + "convertedRgb565" : [ -122 ] } }, "diagnostics" : [ ] @@ -78,14 +78,14 @@ "last_modified" : 1774359772408, "fingerprint" : "eeb7cc665386299403b7be1c272375d5077f3647c587f8033aa8c9275f840562", "metadata" : { - "palette" : { - "originalArgb8888" : [ -265674 ], - "convertedRgb565" : [ -122 ] - }, "tile" : { "width" : 32, "height" : 32, "paletteIndices" : "AQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAAAAAAAAAAABAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEAAAAAAAAAAAEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQAAAAAAAAAAAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAAAAAAAAAAABAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEAAAAAAAAAAAEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQAAAAAAAAAAAQEBAQEBAQEBAQEBAAAAAAAAAAAAAAAAAAAAAAAAAAABAQEBAQEBAQEBAQEAAAAAAAAAAAAAAAAAAAAAAAAAAAEBAQEBAQEBAQEBAQAAAAAAAAAAAAAAAAAAAAAAAAAAAQEBAQEBAQEBAQEBAAAAAAAAAAAAAAAAAAAAAAAAAAABAQEBAQEBAQEBAQEAAAAAAAAAAAAAAAAAAAAAAAAAAAEBAQEBAQEBAQEBAQAAAAAAAAAAAAAAAAAAAAAAAAAAAQEBAQEBAQEBAQEBAAAAAAAAAAAAAAAAAAAAAAAAAAABAQEBAQEBAQEBAQEAAAAAAAAAAAAAAAAAAAAAAAAAAAEBAQEBAQEBAQEBAQAAAAAAAAAAAAAAAAAAAQEBAQEBAQEBAQEBAQEBAQEBAAAAAAAAAAAAAAAAAAABAQEBAQEBAQEBAQEBAQEBAQEAAAAAAAAAAAAAAAAAAAEBAQEBAQEBAQEBAQEBAQEBAQAAAAAAAAAAAAAAAAAAAQEBAQEBAQEBAQEBAAAAAAAAAAAAAAAAAAAAAAAAAAABAQEBAQEBAQEBAQEAAAAAAAAAAAAAAAAAAAAAAAAAAAEBAQEBAQEBAQEBAQAAAAAAAAAAAAAAAAAAAQEBAQEBAQEBAQEBAQEBAQEBAAAAAAAAAAAAAAAAAAABAQEBAQEBAQEBAQEBAQEBAQEAAAAAAAAAAAAAAAAAAAEBAQEBAQEBAQEBAQEBAQEBAQAAAAAAAAAAAAAAAAAAAQEBAQEBAQEBAQEBAQEBAQEBAAAAAAAAAAAAAAAAAAABAQEBAQEBAQEBAQEBAQEBAQEAAAAAAAAAAAAAAAAAAAEBAQEBAQEBAQEBAQ==" + }, + "palette" : { + "originalArgb8888" : [ -265674 ], + "convertedRgb565" : [ -122 ] } }, "diagnostics" : [ ] @@ -96,14 +96,14 @@ "last_modified" : 1774359772409, "fingerprint" : "eeb7cc665386299403b7be1c272375d5077f3647c587f8033aa8c9275f840562", "metadata" : { - "palette" : { - "originalArgb8888" : [ -265674 ], - "convertedRgb565" : [ -122 ] - }, "tile" : { "width" : 32, "height" : 32, "paletteIndices" : "AQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAAAAAAAAAAABAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEAAAAAAAAAAAEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQAAAAAAAAAAAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAAAAAAAAAAABAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEAAAAAAAAAAAEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQAAAAAAAAAAAQEBAQEBAQEBAQEBAAAAAAAAAAAAAAAAAAAAAAAAAAABAQEBAQEBAQEBAQEAAAAAAAAAAAAAAAAAAAAAAAAAAAEBAQEBAQEBAQEBAQAAAAAAAAAAAAAAAAAAAAAAAAAAAQEBAQEBAQEBAQEBAAAAAAAAAAAAAAAAAAAAAAAAAAABAQEBAQEBAQEBAQEAAAAAAAAAAAAAAAAAAAAAAAAAAAEBAQEBAQEBAQEBAQAAAAAAAAAAAAAAAAAAAAAAAAAAAQEBAQEBAQEBAQEBAAAAAAAAAAAAAAAAAAAAAAAAAAABAQEBAQEBAQEBAQEAAAAAAAAAAAAAAAAAAAAAAAAAAAEBAQEBAQEBAQEBAQAAAAAAAAAAAAAAAAAAAQEBAQEBAQEBAQEBAQEBAQEBAAAAAAAAAAAAAAAAAAABAQEBAQEBAQEBAQEBAQEBAQEAAAAAAAAAAAAAAAAAAAEBAQEBAQEBAQEBAQEBAQEBAQAAAAAAAAAAAAAAAAAAAQEBAQEBAQEBAQEBAAAAAAAAAAAAAAAAAAAAAAAAAAABAQEBAQEBAQEBAQEAAAAAAAAAAAAAAAAAAAAAAAAAAAEBAQEBAQEBAQEBAQAAAAAAAAAAAAAAAAAAAQEBAQEBAQEBAQEBAQEBAQEBAAAAAAAAAAAAAAAAAAABAQEBAQEBAQEBAQEBAQEBAQEAAAAAAAAAAAAAAAAAAAEBAQEBAQEBAQEBAQEBAQEBAQAAAAAAAAAAAAAAAAAAAQEBAQEBAQEBAQEBAQEBAQEBAAAAAAAAAAAAAAAAAAABAQEBAQEBAQEBAQEBAQEBAQEAAAAAAAAAAAAAAAAAAAEBAQEBAQEBAQEBAQ==" + }, + "palette" : { + "originalArgb8888" : [ -265674 ], + "convertedRgb565" : [ -122 ] } }, "diagnostics" : [ ] @@ -114,14 +114,14 @@ "last_modified" : 1774359772411, "fingerprint" : "eeb7cc665386299403b7be1c272375d5077f3647c587f8033aa8c9275f840562", "metadata" : { - "palette" : { - "originalArgb8888" : [ -265674 ], - "convertedRgb565" : [ -122 ] - }, "tile" : { "width" : 32, "height" : 32, "paletteIndices" : "AQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAAAAAAAAAAABAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEAAAAAAAAAAAEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQAAAAAAAAAAAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAAAAAAAAAAABAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEAAAAAAAAAAAEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQAAAAAAAAAAAQEBAQEBAQEBAQEBAAAAAAAAAAAAAAAAAAAAAAAAAAABAQEBAQEBAQEBAQEAAAAAAAAAAAAAAAAAAAAAAAAAAAEBAQEBAQEBAQEBAQAAAAAAAAAAAAAAAAAAAAAAAAAAAQEBAQEBAQEBAQEBAAAAAAAAAAAAAAAAAAAAAAAAAAABAQEBAQEBAQEBAQEAAAAAAAAAAAAAAAAAAAAAAAAAAAEBAQEBAQEBAQEBAQAAAAAAAAAAAAAAAAAAAAAAAAAAAQEBAQEBAQEBAQEBAAAAAAAAAAAAAAAAAAAAAAAAAAABAQEBAQEBAQEBAQEAAAAAAAAAAAAAAAAAAAAAAAAAAAEBAQEBAQEBAQEBAQAAAAAAAAAAAAAAAAAAAQEBAQEBAQEBAQEBAQEBAQEBAAAAAAAAAAAAAAAAAAABAQEBAQEBAQEBAQEBAQEBAQEAAAAAAAAAAAAAAAAAAAEBAQEBAQEBAQEBAQEBAQEBAQAAAAAAAAAAAAAAAAAAAQEBAQEBAQEBAQEBAAAAAAAAAAAAAAAAAAAAAAAAAAABAQEBAQEBAQEBAQEAAAAAAAAAAAAAAAAAAAAAAAAAAAEBAQEBAQEBAQEBAQAAAAAAAAAAAAAAAAAAAQEBAQEBAQEBAQEBAQEBAQEBAAAAAAAAAAAAAAAAAAABAQEBAQEBAQEBAQEBAQEBAQEAAAAAAAAAAAAAAAAAAAEBAQEBAQEBAQEBAQEBAQEBAQAAAAAAAAAAAAAAAAAAAQEBAQEBAQEBAQEBAQEBAQEBAAAAAAAAAAAAAAAAAAABAQEBAQEBAQEBAQEBAQEBAQEAAAAAAAAAAAAAAAAAAAEBAQEBAQEBAQEBAQ==" + }, + "palette" : { + "originalArgb8888" : [ -265674 ], + "convertedRgb565" : [ -122 ] } }, "diagnostics" : [ ] @@ -132,14 +132,14 @@ "last_modified" : 1774359772412, "fingerprint" : "eeb7cc665386299403b7be1c272375d5077f3647c587f8033aa8c9275f840562", "metadata" : { - "palette" : { - "originalArgb8888" : [ -265674 ], - "convertedRgb565" : [ -122 ] - }, "tile" : { "width" : 32, "height" : 32, "paletteIndices" : "AQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAAAAAAAAAAABAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEAAAAAAAAAAAEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQAAAAAAAAAAAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAAAAAAAAAAABAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEAAAAAAAAAAAEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQAAAAAAAAAAAQEBAQEBAQEBAQEBAAAAAAAAAAAAAAAAAAAAAAAAAAABAQEBAQEBAQEBAQEAAAAAAAAAAAAAAAAAAAAAAAAAAAEBAQEBAQEBAQEBAQAAAAAAAAAAAAAAAAAAAAAAAAAAAQEBAQEBAQEBAQEBAAAAAAAAAAAAAAAAAAAAAAAAAAABAQEBAQEBAQEBAQEAAAAAAAAAAAAAAAAAAAAAAAAAAAEBAQEBAQEBAQEBAQAAAAAAAAAAAAAAAAAAAAAAAAAAAQEBAQEBAQEBAQEBAAAAAAAAAAAAAAAAAAAAAAAAAAABAQEBAQEBAQEBAQEAAAAAAAAAAAAAAAAAAAAAAAAAAAEBAQEBAQEBAQEBAQAAAAAAAAAAAAAAAAAAAQEBAQEBAQEBAQEBAQEBAQEBAAAAAAAAAAAAAAAAAAABAQEBAQEBAQEBAQEBAQEBAQEAAAAAAAAAAAAAAAAAAAEBAQEBAQEBAQEBAQEBAQEBAQAAAAAAAAAAAAAAAAAAAQEBAQEBAQEBAQEBAAAAAAAAAAAAAAAAAAAAAAAAAAABAQEBAQEBAQEBAQEAAAAAAAAAAAAAAAAAAAAAAAAAAAEBAQEBAQEBAQEBAQAAAAAAAAAAAAAAAAAAAQEBAQEBAQEBAQEBAQEBAQEBAAAAAAAAAAAAAAAAAAABAQEBAQEBAQEBAQEBAQEBAQEAAAAAAAAAAAAAAAAAAAEBAQEBAQEBAQEBAQEBAQEBAQAAAAAAAAAAAAAAAAAAAQEBAQEBAQEBAQEBAQEBAQEBAAAAAAAAAAAAAAAAAAABAQEBAQEBAQEBAQEBAQEBAQEAAAAAAAAAAAAAAAAAAAEBAQEBAQEBAQEBAQ==" + }, + "palette" : { + "originalArgb8888" : [ -265674 ], + "convertedRgb565" : [ -122 ] } }, "diagnostics" : [ ] @@ -150,14 +150,14 @@ "last_modified" : 1774359772413, "fingerprint" : "eeb7cc665386299403b7be1c272375d5077f3647c587f8033aa8c9275f840562", "metadata" : { - "palette" : { - "originalArgb8888" : [ -265674 ], - "convertedRgb565" : [ -122 ] - }, "tile" : { "width" : 32, "height" : 32, "paletteIndices" : "AQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAAAAAAAAAAABAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEAAAAAAAAAAAEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQAAAAAAAAAAAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAAAAAAAAAAABAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEAAAAAAAAAAAEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQAAAAAAAAAAAQEBAQEBAQEBAQEBAAAAAAAAAAAAAAAAAAAAAAAAAAABAQEBAQEBAQEBAQEAAAAAAAAAAAAAAAAAAAAAAAAAAAEBAQEBAQEBAQEBAQAAAAAAAAAAAAAAAAAAAAAAAAAAAQEBAQEBAQEBAQEBAAAAAAAAAAAAAAAAAAAAAAAAAAABAQEBAQEBAQEBAQEAAAAAAAAAAAAAAAAAAAAAAAAAAAEBAQEBAQEBAQEBAQAAAAAAAAAAAAAAAAAAAAAAAAAAAQEBAQEBAQEBAQEBAAAAAAAAAAAAAAAAAAAAAAAAAAABAQEBAQEBAQEBAQEAAAAAAAAAAAAAAAAAAAAAAAAAAAEBAQEBAQEBAQEBAQAAAAAAAAAAAAAAAAAAAQEBAQEBAQEBAQEBAQEBAQEBAAAAAAAAAAAAAAAAAAABAQEBAQEBAQEBAQEBAQEBAQEAAAAAAAAAAAAAAAAAAAEBAQEBAQEBAQEBAQEBAQEBAQAAAAAAAAAAAAAAAAAAAQEBAQEBAQEBAQEBAAAAAAAAAAAAAAAAAAAAAAAAAAABAQEBAQEBAQEBAQEAAAAAAAAAAAAAAAAAAAAAAAAAAAEBAQEBAQEBAQEBAQAAAAAAAAAAAAAAAAAAAQEBAQEBAQEBAQEBAQEBAQEBAAAAAAAAAAAAAAAAAAABAQEBAQEBAQEBAQEBAQEBAQEAAAAAAAAAAAAAAAAAAAEBAQEBAQEBAQEBAQEBAQEBAQAAAAAAAAAAAAAAAAAAAQEBAQEBAQEBAQEBAQEBAQEBAAAAAAAAAAAAAAAAAAABAQEBAQEBAQEBAQEBAQEBAQEAAAAAAAAAAAAAAAAAAAEBAQEBAQEBAQEBAQ==" + }, + "palette" : { + "originalArgb8888" : [ -265674 ], + "convertedRgb565" : [ -122 ] } }, "diagnostics" : [ ] @@ -168,14 +168,14 @@ "last_modified" : 1774359772415, "fingerprint" : "eeb7cc665386299403b7be1c272375d5077f3647c587f8033aa8c9275f840562", "metadata" : { - "palette" : { - "originalArgb8888" : [ -265674 ], - "convertedRgb565" : [ -122 ] - }, "tile" : { "width" : 32, "height" : 32, "paletteIndices" : "AQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAAAAAAAAAAABAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEAAAAAAAAAAAEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQAAAAAAAAAAAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAAAAAAAAAAABAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEAAAAAAAAAAAEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQAAAAAAAAAAAQEBAQEBAQEBAQEBAAAAAAAAAAAAAAAAAAAAAAAAAAABAQEBAQEBAQEBAQEAAAAAAAAAAAAAAAAAAAAAAAAAAAEBAQEBAQEBAQEBAQAAAAAAAAAAAAAAAAAAAAAAAAAAAQEBAQEBAQEBAQEBAAAAAAAAAAAAAAAAAAAAAAAAAAABAQEBAQEBAQEBAQEAAAAAAAAAAAAAAAAAAAAAAAAAAAEBAQEBAQEBAQEBAQAAAAAAAAAAAAAAAAAAAAAAAAAAAQEBAQEBAQEBAQEBAAAAAAAAAAAAAAAAAAAAAAAAAAABAQEBAQEBAQEBAQEAAAAAAAAAAAAAAAAAAAAAAAAAAAEBAQEBAQEBAQEBAQAAAAAAAAAAAAAAAAAAAQEBAQEBAQEBAQEBAQEBAQEBAAAAAAAAAAAAAAAAAAABAQEBAQEBAQEBAQEBAQEBAQEAAAAAAAAAAAAAAAAAAAEBAQEBAQEBAQEBAQEBAQEBAQAAAAAAAAAAAAAAAAAAAQEBAQEBAQEBAQEBAAAAAAAAAAAAAAAAAAAAAAAAAAABAQEBAQEBAQEBAQEAAAAAAAAAAAAAAAAAAAAAAAAAAAEBAQEBAQEBAQEBAQAAAAAAAAAAAAAAAAAAAQEBAQEBAQEBAQEBAQEBAQEBAAAAAAAAAAAAAAAAAAABAQEBAQEBAQEBAQEBAQEBAQEAAAAAAAAAAAAAAAAAAAEBAQEBAQEBAQEBAQEBAQEBAQAAAAAAAAAAAAAAAAAAAQEBAQEBAQEBAQEBAQEBAQEBAAAAAAAAAAAAAAAAAAABAQEBAQEBAQEBAQEBAQEBAQEAAAAAAAAAAAAAAAAAAAEBAQEBAQEBAQEBAQ==" + }, + "palette" : { + "originalArgb8888" : [ -265674 ], + "convertedRgb565" : [ -122 ] } }, "diagnostics" : [ ] @@ -186,14 +186,14 @@ "last_modified" : 1774359772416, "fingerprint" : "eeb7cc665386299403b7be1c272375d5077f3647c587f8033aa8c9275f840562", "metadata" : { - "palette" : { - "originalArgb8888" : [ -265674 ], - "convertedRgb565" : [ -122 ] - }, "tile" : { "width" : 32, "height" : 32, "paletteIndices" : "AQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAAAAAAAAAAABAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEAAAAAAAAAAAEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQAAAAAAAAAAAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAAAAAAAAAAABAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEAAAAAAAAAAAEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQAAAAAAAAAAAQEBAQEBAQEBAQEBAAAAAAAAAAAAAAAAAAAAAAAAAAABAQEBAQEBAQEBAQEAAAAAAAAAAAAAAAAAAAAAAAAAAAEBAQEBAQEBAQEBAQAAAAAAAAAAAAAAAAAAAAAAAAAAAQEBAQEBAQEBAQEBAAAAAAAAAAAAAAAAAAAAAAAAAAABAQEBAQEBAQEBAQEAAAAAAAAAAAAAAAAAAAAAAAAAAAEBAQEBAQEBAQEBAQAAAAAAAAAAAAAAAAAAAAAAAAAAAQEBAQEBAQEBAQEBAAAAAAAAAAAAAAAAAAAAAAAAAAABAQEBAQEBAQEBAQEAAAAAAAAAAAAAAAAAAAAAAAAAAAEBAQEBAQEBAQEBAQAAAAAAAAAAAAAAAAAAAQEBAQEBAQEBAQEBAQEBAQEBAAAAAAAAAAAAAAAAAAABAQEBAQEBAQEBAQEBAQEBAQEAAAAAAAAAAAAAAAAAAAEBAQEBAQEBAQEBAQEBAQEBAQAAAAAAAAAAAAAAAAAAAQEBAQEBAQEBAQEBAAAAAAAAAAAAAAAAAAAAAAAAAAABAQEBAQEBAQEBAQEAAAAAAAAAAAAAAAAAAAAAAAAAAAEBAQEBAQEBAQEBAQAAAAAAAAAAAAAAAAAAAQEBAQEBAQEBAQEBAQEBAQEBAAAAAAAAAAAAAAAAAAABAQEBAQEBAQEBAQEBAQEBAQEAAAAAAAAAAAAAAAAAAAEBAQEBAQEBAQEBAQEBAQEBAQAAAAAAAAAAAAAAAAAAAQEBAQEBAQEBAQEBAQEBAQEBAAAAAAAAAAAAAAAAAAABAQEBAQEBAQEBAQEBAQEBAQEAAAAAAAAAAAAAAAAAAAEBAQEBAQEBAQEBAQ==" + }, + "palette" : { + "originalArgb8888" : [ -265674 ], + "convertedRgb565" : [ -122 ] } }, "diagnostics" : [ ] @@ -204,14 +204,14 @@ "last_modified" : 1774359772417, "fingerprint" : "eeb7cc665386299403b7be1c272375d5077f3647c587f8033aa8c9275f840562", "metadata" : { - "palette" : { - "originalArgb8888" : [ -265674 ], - "convertedRgb565" : [ -122 ] - }, "tile" : { "width" : 32, "height" : 32, "paletteIndices" : "AQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAAAAAAAAAAABAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEAAAAAAAAAAAEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQAAAAAAAAAAAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAAAAAAAAAAABAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEAAAAAAAAAAAEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQAAAAAAAAAAAQEBAQEBAQEBAQEBAAAAAAAAAAAAAAAAAAAAAAAAAAABAQEBAQEBAQEBAQEAAAAAAAAAAAAAAAAAAAAAAAAAAAEBAQEBAQEBAQEBAQAAAAAAAAAAAAAAAAAAAAAAAAAAAQEBAQEBAQEBAQEBAAAAAAAAAAAAAAAAAAAAAAAAAAABAQEBAQEBAQEBAQEAAAAAAAAAAAAAAAAAAAAAAAAAAAEBAQEBAQEBAQEBAQAAAAAAAAAAAAAAAAAAAAAAAAAAAQEBAQEBAQEBAQEBAAAAAAAAAAAAAAAAAAAAAAAAAAABAQEBAQEBAQEBAQEAAAAAAAAAAAAAAAAAAAAAAAAAAAEBAQEBAQEBAQEBAQAAAAAAAAAAAAAAAAAAAQEBAQEBAQEBAQEBAQEBAQEBAAAAAAAAAAAAAAAAAAABAQEBAQEBAQEBAQEBAQEBAQEAAAAAAAAAAAAAAAAAAAEBAQEBAQEBAQEBAQEBAQEBAQAAAAAAAAAAAAAAAAAAAQEBAQEBAQEBAQEBAAAAAAAAAAAAAAAAAAAAAAAAAAABAQEBAQEBAQEBAQEAAAAAAAAAAAAAAAAAAAAAAAAAAAEBAQEBAQEBAQEBAQAAAAAAAAAAAAAAAAAAAQEBAQEBAQEBAQEBAQEBAQEBAAAAAAAAAAAAAAAAAAABAQEBAQEBAQEBAQEBAQEBAQEAAAAAAAAAAAAAAAAAAAEBAQEBAQEBAQEBAQEBAQEBAQAAAAAAAAAAAAAAAAAAAQEBAQEBAQEBAQEBAQEBAQEBAAAAAAAAAAAAAAAAAAABAQEBAQEBAQEBAQEBAQEBAQEAAAAAAAAAAAAAAAAAAAEBAQEBAQEBAQEBAQ==" + }, + "palette" : { + "originalArgb8888" : [ -265674 ], + "convertedRgb565" : [ -122 ] } }, "diagnostics" : [ ] @@ -222,14 +222,14 @@ "last_modified" : 1774359772418, "fingerprint" : "eeb7cc665386299403b7be1c272375d5077f3647c587f8033aa8c9275f840562", "metadata" : { - "palette" : { - "originalArgb8888" : [ -265674 ], - "convertedRgb565" : [ -122 ] - }, "tile" : { "width" : 32, "height" : 32, "paletteIndices" : "AQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAAAAAAAAAAABAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEAAAAAAAAAAAEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQAAAAAAAAAAAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAAAAAAAAAAABAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEAAAAAAAAAAAEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQAAAAAAAAAAAQEBAQEBAQEBAQEBAAAAAAAAAAAAAAAAAAAAAAAAAAABAQEBAQEBAQEBAQEAAAAAAAAAAAAAAAAAAAAAAAAAAAEBAQEBAQEBAQEBAQAAAAAAAAAAAAAAAAAAAAAAAAAAAQEBAQEBAQEBAQEBAAAAAAAAAAAAAAAAAAAAAAAAAAABAQEBAQEBAQEBAQEAAAAAAAAAAAAAAAAAAAAAAAAAAAEBAQEBAQEBAQEBAQAAAAAAAAAAAAAAAAAAAAAAAAAAAQEBAQEBAQEBAQEBAAAAAAAAAAAAAAAAAAAAAAAAAAABAQEBAQEBAQEBAQEAAAAAAAAAAAAAAAAAAAAAAAAAAAEBAQEBAQEBAQEBAQAAAAAAAAAAAAAAAAAAAQEBAQEBAQEBAQEBAQEBAQEBAAAAAAAAAAAAAAAAAAABAQEBAQEBAQEBAQEBAQEBAQEAAAAAAAAAAAAAAAAAAAEBAQEBAQEBAQEBAQEBAQEBAQAAAAAAAAAAAAAAAAAAAQEBAQEBAQEBAQEBAAAAAAAAAAAAAAAAAAAAAAAAAAABAQEBAQEBAQEBAQEAAAAAAAAAAAAAAAAAAAAAAAAAAAEBAQEBAQEBAQEBAQAAAAAAAAAAAAAAAAAAAQEBAQEBAQEBAQEBAQEBAQEBAAAAAAAAAAAAAAAAAAABAQEBAQEBAQEBAQEBAQEBAQEAAAAAAAAAAAAAAAAAAAEBAQEBAQEBAQEBAQEBAQEBAQAAAAAAAAAAAAAAAAAAAQEBAQEBAQEBAQEBAQEBAQEBAAAAAAAAAAAAAAAAAAABAQEBAQEBAQEBAQEBAQEBAQEAAAAAAAAAAAAAAAAAAAEBAQEBAQEBAQEBAQ==" + }, + "palette" : { + "originalArgb8888" : [ -265674 ], + "convertedRgb565" : [ -122 ] } }, "diagnostics" : [ ] @@ -240,14 +240,14 @@ "last_modified" : 1774359772420, "fingerprint" : "eeb7cc665386299403b7be1c272375d5077f3647c587f8033aa8c9275f840562", "metadata" : { - "palette" : { - "originalArgb8888" : [ -265674 ], - "convertedRgb565" : [ -122 ] - }, "tile" : { "width" : 32, "height" : 32, "paletteIndices" : "AQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAAAAAAAAAAABAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEAAAAAAAAAAAEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQAAAAAAAAAAAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAAAAAAAAAAABAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEAAAAAAAAAAAEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQAAAAAAAAAAAQEBAQEBAQEBAQEBAAAAAAAAAAAAAAAAAAAAAAAAAAABAQEBAQEBAQEBAQEAAAAAAAAAAAAAAAAAAAAAAAAAAAEBAQEBAQEBAQEBAQAAAAAAAAAAAAAAAAAAAAAAAAAAAQEBAQEBAQEBAQEBAAAAAAAAAAAAAAAAAAAAAAAAAAABAQEBAQEBAQEBAQEAAAAAAAAAAAAAAAAAAAAAAAAAAAEBAQEBAQEBAQEBAQAAAAAAAAAAAAAAAAAAAAAAAAAAAQEBAQEBAQEBAQEBAAAAAAAAAAAAAAAAAAAAAAAAAAABAQEBAQEBAQEBAQEAAAAAAAAAAAAAAAAAAAAAAAAAAAEBAQEBAQEBAQEBAQAAAAAAAAAAAAAAAAAAAQEBAQEBAQEBAQEBAQEBAQEBAAAAAAAAAAAAAAAAAAABAQEBAQEBAQEBAQEBAQEBAQEAAAAAAAAAAAAAAAAAAAEBAQEBAQEBAQEBAQEBAQEBAQAAAAAAAAAAAAAAAAAAAQEBAQEBAQEBAQEBAAAAAAAAAAAAAAAAAAAAAAAAAAABAQEBAQEBAQEBAQEAAAAAAAAAAAAAAAAAAAAAAAAAAAEBAQEBAQEBAQEBAQAAAAAAAAAAAAAAAAAAAQEBAQEBAQEBAQEBAQEBAQEBAAAAAAAAAAAAAAAAAAABAQEBAQEBAQEBAQEBAQEBAQEAAAAAAAAAAAAAAAAAAAEBAQEBAQEBAQEBAQEBAQEBAQAAAAAAAAAAAAAAAAAAAQEBAQEBAQEBAQEBAQEBAQEBAAAAAAAAAAAAAAAAAAABAQEBAQEBAQEBAQEBAQEBAQEAAAAAAAAAAAAAAAAAAAEBAQEBAQEBAQEBAQ==" + }, + "palette" : { + "originalArgb8888" : [ -265674 ], + "convertedRgb565" : [ -122 ] } }, "diagnostics" : [ ] @@ -258,14 +258,14 @@ "last_modified" : 1774359772421, "fingerprint" : "eeb7cc665386299403b7be1c272375d5077f3647c587f8033aa8c9275f840562", "metadata" : { - "palette" : { - "originalArgb8888" : [ -265674 ], - "convertedRgb565" : [ -122 ] - }, "tile" : { "width" : 32, "height" : 32, "paletteIndices" : "AQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAAAAAAAAAAABAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEAAAAAAAAAAAEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQAAAAAAAAAAAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAAAAAAAAAAABAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEAAAAAAAAAAAEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQAAAAAAAAAAAQEBAQEBAQEBAQEBAAAAAAAAAAAAAAAAAAAAAAAAAAABAQEBAQEBAQEBAQEAAAAAAAAAAAAAAAAAAAAAAAAAAAEBAQEBAQEBAQEBAQAAAAAAAAAAAAAAAAAAAAAAAAAAAQEBAQEBAQEBAQEBAAAAAAAAAAAAAAAAAAAAAAAAAAABAQEBAQEBAQEBAQEAAAAAAAAAAAAAAAAAAAAAAAAAAAEBAQEBAQEBAQEBAQAAAAAAAAAAAAAAAAAAAAAAAAAAAQEBAQEBAQEBAQEBAAAAAAAAAAAAAAAAAAAAAAAAAAABAQEBAQEBAQEBAQEAAAAAAAAAAAAAAAAAAAAAAAAAAAEBAQEBAQEBAQEBAQAAAAAAAAAAAAAAAAAAAQEBAQEBAQEBAQEBAQEBAQEBAAAAAAAAAAAAAAAAAAABAQEBAQEBAQEBAQEBAQEBAQEAAAAAAAAAAAAAAAAAAAEBAQEBAQEBAQEBAQEBAQEBAQAAAAAAAAAAAAAAAAAAAQEBAQEBAQEBAQEBAAAAAAAAAAAAAAAAAAAAAAAAAAABAQEBAQEBAQEBAQEAAAAAAAAAAAAAAAAAAAAAAAAAAAEBAQEBAQEBAQEBAQAAAAAAAAAAAAAAAAAAAQEBAQEBAQEBAQEBAQEBAQEBAAAAAAAAAAAAAAAAAAABAQEBAQEBAQEBAQEBAQEBAQEAAAAAAAAAAAAAAAAAAAEBAQEBAQEBAQEBAQEBAQEBAQAAAAAAAAAAAAAAAAAAAQEBAQEBAQEBAQEBAQEBAQEBAAAAAAAAAAAAAAAAAAABAQEBAQEBAQEBAQEBAQEBAQEAAAAAAAAAAAAAAAAAAAEBAQEBAQEBAQEBAQ==" + }, + "palette" : { + "originalArgb8888" : [ -265674 ], + "convertedRgb565" : [ -122 ] } }, "diagnostics" : [ ] @@ -276,14 +276,14 @@ "last_modified" : 1774359772423, "fingerprint" : "eeb7cc665386299403b7be1c272375d5077f3647c587f8033aa8c9275f840562", "metadata" : { - "palette" : { - "originalArgb8888" : [ -265674 ], - "convertedRgb565" : [ -122 ] - }, "tile" : { "width" : 32, "height" : 32, "paletteIndices" : "AQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAAAAAAAAAAABAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEAAAAAAAAAAAEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQAAAAAAAAAAAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAAAAAAAAAAABAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEAAAAAAAAAAAEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQAAAAAAAAAAAQEBAQEBAQEBAQEBAAAAAAAAAAAAAAAAAAAAAAAAAAABAQEBAQEBAQEBAQEAAAAAAAAAAAAAAAAAAAAAAAAAAAEBAQEBAQEBAQEBAQAAAAAAAAAAAAAAAAAAAAAAAAAAAQEBAQEBAQEBAQEBAAAAAAAAAAAAAAAAAAAAAAAAAAABAQEBAQEBAQEBAQEAAAAAAAAAAAAAAAAAAAAAAAAAAAEBAQEBAQEBAQEBAQAAAAAAAAAAAAAAAAAAAAAAAAAAAQEBAQEBAQEBAQEBAAAAAAAAAAAAAAAAAAAAAAAAAAABAQEBAQEBAQEBAQEAAAAAAAAAAAAAAAAAAAAAAAAAAAEBAQEBAQEBAQEBAQAAAAAAAAAAAAAAAAAAAQEBAQEBAQEBAQEBAQEBAQEBAAAAAAAAAAAAAAAAAAABAQEBAQEBAQEBAQEBAQEBAQEAAAAAAAAAAAAAAAAAAAEBAQEBAQEBAQEBAQEBAQEBAQAAAAAAAAAAAAAAAAAAAQEBAQEBAQEBAQEBAAAAAAAAAAAAAAAAAAAAAAAAAAABAQEBAQEBAQEBAQEAAAAAAAAAAAAAAAAAAAAAAAAAAAEBAQEBAQEBAQEBAQAAAAAAAAAAAAAAAAAAAQEBAQEBAQEBAQEBAQEBAQEBAAAAAAAAAAAAAAAAAAABAQEBAQEBAQEBAQEBAQEBAQEAAAAAAAAAAAAAAAAAAAEBAQEBAQEBAQEBAQEBAQEBAQAAAAAAAAAAAAAAAAAAAQEBAQEBAQEBAQEBAQEBAQEBAAAAAAAAAAAAAAAAAAABAQEBAQEBAQEBAQEBAQEBAQEAAAAAAAAAAAAAAAAAAAEBAQEBAQEBAQEBAQ==" + }, + "palette" : { + "originalArgb8888" : [ -265674 ], + "convertedRgb565" : [ -122 ] } }, "diagnostics" : [ ] @@ -294,14 +294,14 @@ "last_modified" : 1774359772424, "fingerprint" : "eeb7cc665386299403b7be1c272375d5077f3647c587f8033aa8c9275f840562", "metadata" : { - "palette" : { - "originalArgb8888" : [ -265674 ], - "convertedRgb565" : [ -122 ] - }, "tile" : { "width" : 32, "height" : 32, "paletteIndices" : "AQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAAAAAAAAAAABAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEAAAAAAAAAAAEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQAAAAAAAAAAAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAAAAAAAAAAABAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEAAAAAAAAAAAEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQAAAAAAAAAAAQEBAQEBAQEBAQEBAAAAAAAAAAAAAAAAAAAAAAAAAAABAQEBAQEBAQEBAQEAAAAAAAAAAAAAAAAAAAAAAAAAAAEBAQEBAQEBAQEBAQAAAAAAAAAAAAAAAAAAAAAAAAAAAQEBAQEBAQEBAQEBAAAAAAAAAAAAAAAAAAAAAAAAAAABAQEBAQEBAQEBAQEAAAAAAAAAAAAAAAAAAAAAAAAAAAEBAQEBAQEBAQEBAQAAAAAAAAAAAAAAAAAAAAAAAAAAAQEBAQEBAQEBAQEBAAAAAAAAAAAAAAAAAAAAAAAAAAABAQEBAQEBAQEBAQEAAAAAAAAAAAAAAAAAAAAAAAAAAAEBAQEBAQEBAQEBAQAAAAAAAAAAAAAAAAAAAQEBAQEBAQEBAQEBAQEBAQEBAAAAAAAAAAAAAAAAAAABAQEBAQEBAQEBAQEBAQEBAQEAAAAAAAAAAAAAAAAAAAEBAQEBAQEBAQEBAQEBAQEBAQAAAAAAAAAAAAAAAAAAAQEBAQEBAQEBAQEBAAAAAAAAAAAAAAAAAAAAAAAAAAABAQEBAQEBAQEBAQEAAAAAAAAAAAAAAAAAAAAAAAAAAAEBAQEBAQEBAQEBAQAAAAAAAAAAAAAAAAAAAQEBAQEBAQEBAQEBAQEBAQEBAAAAAAAAAAAAAAAAAAABAQEBAQEBAQEBAQEBAQEBAQEAAAAAAAAAAAAAAAAAAAEBAQEBAQEBAQEBAQEBAQEBAQAAAAAAAAAAAAAAAAAAAQEBAQEBAQEBAQEBAQEBAQEBAAAAAAAAAAAAAAAAAAABAQEBAQEBAQEBAQEBAQEBAQEAAAAAAAAAAAAAAAAAAAEBAQEBAQEBAQEBAQ==" + }, + "palette" : { + "originalArgb8888" : [ -265674 ], + "convertedRgb565" : [ -122 ] } }, "diagnostics" : [ ] @@ -312,14 +312,14 @@ "last_modified" : 1774359772425, "fingerprint" : "eeb7cc665386299403b7be1c272375d5077f3647c587f8033aa8c9275f840562", "metadata" : { - "palette" : { - "originalArgb8888" : [ -265674 ], - "convertedRgb565" : [ -122 ] - }, "tile" : { "width" : 32, "height" : 32, "paletteIndices" : "AQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAAAAAAAAAAABAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEAAAAAAAAAAAEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQAAAAAAAAAAAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAAAAAAAAAAABAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEAAAAAAAAAAAEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQAAAAAAAAAAAQEBAQEBAQEBAQEBAAAAAAAAAAAAAAAAAAAAAAAAAAABAQEBAQEBAQEBAQEAAAAAAAAAAAAAAAAAAAAAAAAAAAEBAQEBAQEBAQEBAQAAAAAAAAAAAAAAAAAAAAAAAAAAAQEBAQEBAQEBAQEBAAAAAAAAAAAAAAAAAAAAAAAAAAABAQEBAQEBAQEBAQEAAAAAAAAAAAAAAAAAAAAAAAAAAAEBAQEBAQEBAQEBAQAAAAAAAAAAAAAAAAAAAAAAAAAAAQEBAQEBAQEBAQEBAAAAAAAAAAAAAAAAAAAAAAAAAAABAQEBAQEBAQEBAQEAAAAAAAAAAAAAAAAAAAAAAAAAAAEBAQEBAQEBAQEBAQAAAAAAAAAAAAAAAAAAAQEBAQEBAQEBAQEBAQEBAQEBAAAAAAAAAAAAAAAAAAABAQEBAQEBAQEBAQEBAQEBAQEAAAAAAAAAAAAAAAAAAAEBAQEBAQEBAQEBAQEBAQEBAQAAAAAAAAAAAAAAAAAAAQEBAQEBAQEBAQEBAAAAAAAAAAAAAAAAAAAAAAAAAAABAQEBAQEBAQEBAQEAAAAAAAAAAAAAAAAAAAAAAAAAAAEBAQEBAQEBAQEBAQAAAAAAAAAAAAAAAAAAAQEBAQEBAQEBAQEBAQEBAQEBAAAAAAAAAAAAAAAAAAABAQEBAQEBAQEBAQEBAQEBAQEAAAAAAAAAAAAAAAAAAAEBAQEBAQEBAQEBAQEBAQEBAQAAAAAAAAAAAAAAAAAAAQEBAQEBAQEBAQEBAQEBAQEBAAAAAAAAAAAAAAAAAAABAQEBAQEBAQEBAQEBAQEBAQEAAAAAAAAAAAAAAAAAAAEBAQEBAQEBAQEBAQ==" + }, + "palette" : { + "originalArgb8888" : [ -265674 ], + "convertedRgb565" : [ -122 ] } }, "diagnostics" : [ ] @@ -330,14 +330,14 @@ "last_modified" : 1774359772426, "fingerprint" : "eeb7cc665386299403b7be1c272375d5077f3647c587f8033aa8c9275f840562", "metadata" : { - "palette" : { - "originalArgb8888" : [ -265674 ], - "convertedRgb565" : [ -122 ] - }, "tile" : { "width" : 32, "height" : 32, "paletteIndices" : "AQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAAAAAAAAAAABAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEAAAAAAAAAAAEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQAAAAAAAAAAAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAAAAAAAAAAABAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEAAAAAAAAAAAEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQAAAAAAAAAAAQEBAQEBAQEBAQEBAAAAAAAAAAAAAAAAAAAAAAAAAAABAQEBAQEBAQEBAQEAAAAAAAAAAAAAAAAAAAAAAAAAAAEBAQEBAQEBAQEBAQAAAAAAAAAAAAAAAAAAAAAAAAAAAQEBAQEBAQEBAQEBAAAAAAAAAAAAAAAAAAAAAAAAAAABAQEBAQEBAQEBAQEAAAAAAAAAAAAAAAAAAAAAAAAAAAEBAQEBAQEBAQEBAQAAAAAAAAAAAAAAAAAAAAAAAAAAAQEBAQEBAQEBAQEBAAAAAAAAAAAAAAAAAAAAAAAAAAABAQEBAQEBAQEBAQEAAAAAAAAAAAAAAAAAAAAAAAAAAAEBAQEBAQEBAQEBAQAAAAAAAAAAAAAAAAAAAQEBAQEBAQEBAQEBAQEBAQEBAAAAAAAAAAAAAAAAAAABAQEBAQEBAQEBAQEBAQEBAQEAAAAAAAAAAAAAAAAAAAEBAQEBAQEBAQEBAQEBAQEBAQAAAAAAAAAAAAAAAAAAAQEBAQEBAQEBAQEBAAAAAAAAAAAAAAAAAAAAAAAAAAABAQEBAQEBAQEBAQEAAAAAAAAAAAAAAAAAAAAAAAAAAAEBAQEBAQEBAQEBAQAAAAAAAAAAAAAAAAAAAQEBAQEBAQEBAQEBAQEBAQEBAAAAAAAAAAAAAAAAAAABAQEBAQEBAQEBAQEBAQEBAQEAAAAAAAAAAAAAAAAAAAEBAQEBAQEBAQEBAQEBAQEBAQAAAAAAAAAAAAAAAAAAAQEBAQEBAQEBAQEBAQEBAQEBAAAAAAAAAAAAAAAAAAABAQEBAQEBAQEBAQEBAQEBAQEAAAAAAAAAAAAAAAAAAAEBAQEBAQEBAQEBAQ==" + }, + "palette" : { + "originalArgb8888" : [ -265674 ], + "convertedRgb565" : [ -122 ] } }, "diagnostics" : [ ] @@ -348,14 +348,14 @@ "last_modified" : 1774359772428, "fingerprint" : "eeb7cc665386299403b7be1c272375d5077f3647c587f8033aa8c9275f840562", "metadata" : { - "palette" : { - "originalArgb8888" : [ -265674 ], - "convertedRgb565" : [ -122 ] - }, "tile" : { "width" : 32, "height" : 32, "paletteIndices" : "AQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAAAAAAAAAAABAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEAAAAAAAAAAAEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQAAAAAAAAAAAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAAAAAAAAAAABAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEAAAAAAAAAAAEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQAAAAAAAAAAAQEBAQEBAQEBAQEBAAAAAAAAAAAAAAAAAAAAAAAAAAABAQEBAQEBAQEBAQEAAAAAAAAAAAAAAAAAAAAAAAAAAAEBAQEBAQEBAQEBAQAAAAAAAAAAAAAAAAAAAAAAAAAAAQEBAQEBAQEBAQEBAAAAAAAAAAAAAAAAAAAAAAAAAAABAQEBAQEBAQEBAQEAAAAAAAAAAAAAAAAAAAAAAAAAAAEBAQEBAQEBAQEBAQAAAAAAAAAAAAAAAAAAAAAAAAAAAQEBAQEBAQEBAQEBAAAAAAAAAAAAAAAAAAAAAAAAAAABAQEBAQEBAQEBAQEAAAAAAAAAAAAAAAAAAAAAAAAAAAEBAQEBAQEBAQEBAQAAAAAAAAAAAAAAAAAAAQEBAQEBAQEBAQEBAQEBAQEBAAAAAAAAAAAAAAAAAAABAQEBAQEBAQEBAQEBAQEBAQEAAAAAAAAAAAAAAAAAAAEBAQEBAQEBAQEBAQEBAQEBAQAAAAAAAAAAAAAAAAAAAQEBAQEBAQEBAQEBAAAAAAAAAAAAAAAAAAAAAAAAAAABAQEBAQEBAQEBAQEAAAAAAAAAAAAAAAAAAAAAAAAAAAEBAQEBAQEBAQEBAQAAAAAAAAAAAAAAAAAAAQEBAQEBAQEBAQEBAQEBAQEBAAAAAAAAAAAAAAAAAAABAQEBAQEBAQEBAQEBAQEBAQEAAAAAAAAAAAAAAAAAAAEBAQEBAQEBAQEBAQEBAQEBAQAAAAAAAAAAAAAAAAAAAQEBAQEBAQEBAQEBAQEBAQEBAAAAAAAAAAAAAAAAAAABAQEBAQEBAQEBAQEBAQEBAQEAAAAAAAAAAAAAAAAAAAEBAQEBAQEBAQEBAQ==" + }, + "palette" : { + "originalArgb8888" : [ -265674 ], + "convertedRgb565" : [ -122 ] } }, "diagnostics" : [ ] @@ -366,14 +366,14 @@ "last_modified" : 1774359772429, "fingerprint" : "eeb7cc665386299403b7be1c272375d5077f3647c587f8033aa8c9275f840562", "metadata" : { - "palette" : { - "originalArgb8888" : [ -265674 ], - "convertedRgb565" : [ -122 ] - }, "tile" : { "width" : 32, "height" : 32, "paletteIndices" : "AQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAAAAAAAAAAABAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEAAAAAAAAAAAEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQAAAAAAAAAAAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAAAAAAAAAAABAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEAAAAAAAAAAAEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQAAAAAAAAAAAQEBAQEBAQEBAQEBAAAAAAAAAAAAAAAAAAAAAAAAAAABAQEBAQEBAQEBAQEAAAAAAAAAAAAAAAAAAAAAAAAAAAEBAQEBAQEBAQEBAQAAAAAAAAAAAAAAAAAAAAAAAAAAAQEBAQEBAQEBAQEBAAAAAAAAAAAAAAAAAAAAAAAAAAABAQEBAQEBAQEBAQEAAAAAAAAAAAAAAAAAAAAAAAAAAAEBAQEBAQEBAQEBAQAAAAAAAAAAAAAAAAAAAAAAAAAAAQEBAQEBAQEBAQEBAAAAAAAAAAAAAAAAAAAAAAAAAAABAQEBAQEBAQEBAQEAAAAAAAAAAAAAAAAAAAAAAAAAAAEBAQEBAQEBAQEBAQAAAAAAAAAAAAAAAAAAAQEBAQEBAQEBAQEBAQEBAQEBAAAAAAAAAAAAAAAAAAABAQEBAQEBAQEBAQEBAQEBAQEAAAAAAAAAAAAAAAAAAAEBAQEBAQEBAQEBAQEBAQEBAQAAAAAAAAAAAAAAAAAAAQEBAQEBAQEBAQEBAAAAAAAAAAAAAAAAAAAAAAAAAAABAQEBAQEBAQEBAQEAAAAAAAAAAAAAAAAAAAAAAAAAAAEBAQEBAQEBAQEBAQAAAAAAAAAAAAAAAAAAAQEBAQEBAQEBAQEBAQEBAQEBAAAAAAAAAAAAAAAAAAABAQEBAQEBAQEBAQEBAQEBAQEAAAAAAAAAAAAAAAAAAAEBAQEBAQEBAQEBAQEBAQEBAQAAAAAAAAAAAAAAAAAAAQEBAQEBAQEBAQEBAQEBAQEBAAAAAAAAAAAAAAAAAAABAQEBAQEBAQEBAQEBAQEBAQEAAAAAAAAAAAAAAAAAAAEBAQEBAQEBAQEBAQ==" + }, + "palette" : { + "originalArgb8888" : [ -265674 ], + "convertedRgb565" : [ -122 ] } }, "diagnostics" : [ ] @@ -384,14 +384,14 @@ "last_modified" : 1774359772430, "fingerprint" : "eeb7cc665386299403b7be1c272375d5077f3647c587f8033aa8c9275f840562", "metadata" : { - "palette" : { - "originalArgb8888" : [ -265674 ], - "convertedRgb565" : [ -122 ] - }, "tile" : { "width" : 32, "height" : 32, "paletteIndices" : "AQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAAAAAAAAAAABAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEAAAAAAAAAAAEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQAAAAAAAAAAAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAAAAAAAAAAABAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEAAAAAAAAAAAEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQAAAAAAAAAAAQEBAQEBAQEBAQEBAAAAAAAAAAAAAAAAAAAAAAAAAAABAQEBAQEBAQEBAQEAAAAAAAAAAAAAAAAAAAAAAAAAAAEBAQEBAQEBAQEBAQAAAAAAAAAAAAAAAAAAAAAAAAAAAQEBAQEBAQEBAQEBAAAAAAAAAAAAAAAAAAAAAAAAAAABAQEBAQEBAQEBAQEAAAAAAAAAAAAAAAAAAAAAAAAAAAEBAQEBAQEBAQEBAQAAAAAAAAAAAAAAAAAAAAAAAAAAAQEBAQEBAQEBAQEBAAAAAAAAAAAAAAAAAAAAAAAAAAABAQEBAQEBAQEBAQEAAAAAAAAAAAAAAAAAAAAAAAAAAAEBAQEBAQEBAQEBAQAAAAAAAAAAAAAAAAAAAQEBAQEBAQEBAQEBAQEBAQEBAAAAAAAAAAAAAAAAAAABAQEBAQEBAQEBAQEBAQEBAQEAAAAAAAAAAAAAAAAAAAEBAQEBAQEBAQEBAQEBAQEBAQAAAAAAAAAAAAAAAAAAAQEBAQEBAQEBAQEBAAAAAAAAAAAAAAAAAAAAAAAAAAABAQEBAQEBAQEBAQEAAAAAAAAAAAAAAAAAAAAAAAAAAAEBAQEBAQEBAQEBAQAAAAAAAAAAAAAAAAAAAQEBAQEBAQEBAQEBAQEBAQEBAAAAAAAAAAAAAAAAAAABAQEBAQEBAQEBAQEBAQEBAQEAAAAAAAAAAAAAAAAAAAEBAQEBAQEBAQEBAQEBAQEBAQAAAAAAAAAAAAAAAAAAAQEBAQEBAQEBAQEBAQEBAQEBAAAAAAAAAAAAAAAAAAABAQEBAQEBAQEBAQEBAQEBAQEAAAAAAAAAAAAAAAAAAAEBAQEBAQEBAQEBAQ==" + }, + "palette" : { + "originalArgb8888" : [ -265674 ], + "convertedRgb565" : [ -122 ] } }, "diagnostics" : [ ] @@ -402,14 +402,14 @@ "last_modified" : 1774359772431, "fingerprint" : "eeb7cc665386299403b7be1c272375d5077f3647c587f8033aa8c9275f840562", "metadata" : { - "palette" : { - "originalArgb8888" : [ -265674 ], - "convertedRgb565" : [ -122 ] - }, "tile" : { "width" : 32, "height" : 32, "paletteIndices" : "AQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAAAAAAAAAAABAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEAAAAAAAAAAAEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQAAAAAAAAAAAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAAAAAAAAAAABAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEAAAAAAAAAAAEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQAAAAAAAAAAAQEBAQEBAQEBAQEBAAAAAAAAAAAAAAAAAAAAAAAAAAABAQEBAQEBAQEBAQEAAAAAAAAAAAAAAAAAAAAAAAAAAAEBAQEBAQEBAQEBAQAAAAAAAAAAAAAAAAAAAAAAAAAAAQEBAQEBAQEBAQEBAAAAAAAAAAAAAAAAAAAAAAAAAAABAQEBAQEBAQEBAQEAAAAAAAAAAAAAAAAAAAAAAAAAAAEBAQEBAQEBAQEBAQAAAAAAAAAAAAAAAAAAAAAAAAAAAQEBAQEBAQEBAQEBAAAAAAAAAAAAAAAAAAAAAAAAAAABAQEBAQEBAQEBAQEAAAAAAAAAAAAAAAAAAAAAAAAAAAEBAQEBAQEBAQEBAQAAAAAAAAAAAAAAAAAAAQEBAQEBAQEBAQEBAQEBAQEBAAAAAAAAAAAAAAAAAAABAQEBAQEBAQEBAQEBAQEBAQEAAAAAAAAAAAAAAAAAAAEBAQEBAQEBAQEBAQEBAQEBAQAAAAAAAAAAAAAAAAAAAQEBAQEBAQEBAQEBAAAAAAAAAAAAAAAAAAAAAAAAAAABAQEBAQEBAQEBAQEAAAAAAAAAAAAAAAAAAAAAAAAAAAEBAQEBAQEBAQEBAQAAAAAAAAAAAAAAAAAAAQEBAQEBAQEBAQEBAQEBAQEBAAAAAAAAAAAAAAAAAAABAQEBAQEBAQEBAQEBAQEBAQEAAAAAAAAAAAAAAAAAAAEBAQEBAQEBAQEBAQEBAQEBAQAAAAAAAAAAAAAAAAAAAQEBAQEBAQEBAQEBAQEBAQEBAAAAAAAAAAAAAAAAAAABAQEBAQEBAQEBAQEBAQEBAQEAAAAAAAAAAAAAAAAAAAEBAQEBAQEBAQEBAQ==" + }, + "palette" : { + "originalArgb8888" : [ -265674 ], + "convertedRgb565" : [ -122 ] } }, "diagnostics" : [ ] @@ -420,14 +420,14 @@ "last_modified" : 1774359772432, "fingerprint" : "eeb7cc665386299403b7be1c272375d5077f3647c587f8033aa8c9275f840562", "metadata" : { - "palette" : { - "originalArgb8888" : [ -265674 ], - "convertedRgb565" : [ -122 ] - }, "tile" : { "width" : 32, "height" : 32, "paletteIndices" : "AQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAAAAAAAAAAABAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEAAAAAAAAAAAEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQAAAAAAAAAAAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAAAAAAAAAAABAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEAAAAAAAAAAAEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQAAAAAAAAAAAQEBAQEBAQEBAQEBAAAAAAAAAAAAAAAAAAAAAAAAAAABAQEBAQEBAQEBAQEAAAAAAAAAAAAAAAAAAAAAAAAAAAEBAQEBAQEBAQEBAQAAAAAAAAAAAAAAAAAAAAAAAAAAAQEBAQEBAQEBAQEBAAAAAAAAAAAAAAAAAAAAAAAAAAABAQEBAQEBAQEBAQEAAAAAAAAAAAAAAAAAAAAAAAAAAAEBAQEBAQEBAQEBAQAAAAAAAAAAAAAAAAAAAAAAAAAAAQEBAQEBAQEBAQEBAAAAAAAAAAAAAAAAAAAAAAAAAAABAQEBAQEBAQEBAQEAAAAAAAAAAAAAAAAAAAAAAAAAAAEBAQEBAQEBAQEBAQAAAAAAAAAAAAAAAAAAAQEBAQEBAQEBAQEBAQEBAQEBAAAAAAAAAAAAAAAAAAABAQEBAQEBAQEBAQEBAQEBAQEAAAAAAAAAAAAAAAAAAAEBAQEBAQEBAQEBAQEBAQEBAQAAAAAAAAAAAAAAAAAAAQEBAQEBAQEBAQEBAAAAAAAAAAAAAAAAAAAAAAAAAAABAQEBAQEBAQEBAQEAAAAAAAAAAAAAAAAAAAAAAAAAAAEBAQEBAQEBAQEBAQAAAAAAAAAAAAAAAAAAAQEBAQEBAQEBAQEBAQEBAQEBAAAAAAAAAAAAAAAAAAABAQEBAQEBAQEBAQEBAQEBAQEAAAAAAAAAAAAAAAAAAAEBAQEBAQEBAQEBAQEBAQEBAQAAAAAAAAAAAAAAAAAAAQEBAQEBAQEBAQEBAQEBAQEBAAAAAAAAAAAAAAAAAAABAQEBAQEBAQEBAQEBAQEBAQEAAAAAAAAAAAAAAAAAAAEBAQEBAQEBAQEBAQ==" + }, + "palette" : { + "originalArgb8888" : [ -265674 ], + "convertedRgb565" : [ -122 ] } }, "diagnostics" : [ ] @@ -438,14 +438,14 @@ "last_modified" : 1774359772433, "fingerprint" : "eeb7cc665386299403b7be1c272375d5077f3647c587f8033aa8c9275f840562", "metadata" : { - "palette" : { - "originalArgb8888" : [ -265674 ], - "convertedRgb565" : [ -122 ] - }, "tile" : { "width" : 32, "height" : 32, "paletteIndices" : "AQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAAAAAAAAAAABAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEAAAAAAAAAAAEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQAAAAAAAAAAAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAAAAAAAAAAABAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEAAAAAAAAAAAEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQAAAAAAAAAAAQEBAQEBAQEBAQEBAAAAAAAAAAAAAAAAAAAAAAAAAAABAQEBAQEBAQEBAQEAAAAAAAAAAAAAAAAAAAAAAAAAAAEBAQEBAQEBAQEBAQAAAAAAAAAAAAAAAAAAAAAAAAAAAQEBAQEBAQEBAQEBAAAAAAAAAAAAAAAAAAAAAAAAAAABAQEBAQEBAQEBAQEAAAAAAAAAAAAAAAAAAAAAAAAAAAEBAQEBAQEBAQEBAQAAAAAAAAAAAAAAAAAAAAAAAAAAAQEBAQEBAQEBAQEBAAAAAAAAAAAAAAAAAAAAAAAAAAABAQEBAQEBAQEBAQEAAAAAAAAAAAAAAAAAAAAAAAAAAAEBAQEBAQEBAQEBAQAAAAAAAAAAAAAAAAAAAQEBAQEBAQEBAQEBAQEBAQEBAAAAAAAAAAAAAAAAAAABAQEBAQEBAQEBAQEBAQEBAQEAAAAAAAAAAAAAAAAAAAEBAQEBAQEBAQEBAQEBAQEBAQAAAAAAAAAAAAAAAAAAAQEBAQEBAQEBAQEBAAAAAAAAAAAAAAAAAAAAAAAAAAABAQEBAQEBAQEBAQEAAAAAAAAAAAAAAAAAAAAAAAAAAAEBAQEBAQEBAQEBAQAAAAAAAAAAAAAAAAAAAQEBAQEBAQEBAQEBAQEBAQEBAAAAAAAAAAAAAAAAAAABAQEBAQEBAQEBAQEBAQEBAQEAAAAAAAAAAAAAAAAAAAEBAQEBAQEBAQEBAQEBAQEBAQAAAAAAAAAAAAAAAAAAAQEBAQEBAQEBAQEBAQEBAQEBAAAAAAAAAAAAAAAAAAABAQEBAQEBAQEBAQEBAQEBAQEAAAAAAAAAAAAAAAAAAAEBAQEBAQEBAQEBAQ==" + }, + "palette" : { + "originalArgb8888" : [ -265674 ], + "convertedRgb565" : [ -122 ] } }, "diagnostics" : [ ] @@ -456,14 +456,14 @@ "last_modified" : 1774359772435, "fingerprint" : "eeb7cc665386299403b7be1c272375d5077f3647c587f8033aa8c9275f840562", "metadata" : { - "palette" : { - "originalArgb8888" : [ -265674 ], - "convertedRgb565" : [ -122 ] - }, "tile" : { "width" : 32, "height" : 32, "paletteIndices" : "AQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAAAAAAAAAAABAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEAAAAAAAAAAAEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQAAAAAAAAAAAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAAAAAAAAAAABAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEAAAAAAAAAAAEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQAAAAAAAAAAAQEBAQEBAQEBAQEBAAAAAAAAAAAAAAAAAAAAAAAAAAABAQEBAQEBAQEBAQEAAAAAAAAAAAAAAAAAAAAAAAAAAAEBAQEBAQEBAQEBAQAAAAAAAAAAAAAAAAAAAAAAAAAAAQEBAQEBAQEBAQEBAAAAAAAAAAAAAAAAAAAAAAAAAAABAQEBAQEBAQEBAQEAAAAAAAAAAAAAAAAAAAAAAAAAAAEBAQEBAQEBAQEBAQAAAAAAAAAAAAAAAAAAAAAAAAAAAQEBAQEBAQEBAQEBAAAAAAAAAAAAAAAAAAAAAAAAAAABAQEBAQEBAQEBAQEAAAAAAAAAAAAAAAAAAAAAAAAAAAEBAQEBAQEBAQEBAQAAAAAAAAAAAAAAAAAAAQEBAQEBAQEBAQEBAQEBAQEBAAAAAAAAAAAAAAAAAAABAQEBAQEBAQEBAQEBAQEBAQEAAAAAAAAAAAAAAAAAAAEBAQEBAQEBAQEBAQEBAQEBAQAAAAAAAAAAAAAAAAAAAQEBAQEBAQEBAQEBAAAAAAAAAAAAAAAAAAAAAAAAAAABAQEBAQEBAQEBAQEAAAAAAAAAAAAAAAAAAAAAAAAAAAEBAQEBAQEBAQEBAQAAAAAAAAAAAAAAAAAAAQEBAQEBAQEBAQEBAQEBAQEBAAAAAAAAAAAAAAAAAAABAQEBAQEBAQEBAQEBAQEBAQEAAAAAAAAAAAAAAAAAAAEBAQEBAQEBAQEBAQEBAQEBAQAAAAAAAAAAAAAAAAAAAQEBAQEBAQEBAQEBAQEBAQEBAAAAAAAAAAAAAAAAAAABAQEBAQEBAQEBAQEBAQEBAQEAAAAAAAAAAAAAAAAAAAEBAQEBAQEBAQEBAQ==" + }, + "palette" : { + "originalArgb8888" : [ -265674 ], + "convertedRgb565" : [ -122 ] } }, "diagnostics" : [ ] @@ -474,14 +474,14 @@ "last_modified" : 1774359772436, "fingerprint" : "eeb7cc665386299403b7be1c272375d5077f3647c587f8033aa8c9275f840562", "metadata" : { - "palette" : { - "originalArgb8888" : [ -265674 ], - "convertedRgb565" : [ -122 ] - }, "tile" : { "width" : 32, "height" : 32, "paletteIndices" : "AQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAAAAAAAAAAABAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEAAAAAAAAAAAEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQAAAAAAAAAAAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAAAAAAAAAAABAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEAAAAAAAAAAAEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQAAAAAAAAAAAQEBAQEBAQEBAQEBAAAAAAAAAAAAAAAAAAAAAAAAAAABAQEBAQEBAQEBAQEAAAAAAAAAAAAAAAAAAAAAAAAAAAEBAQEBAQEBAQEBAQAAAAAAAAAAAAAAAAAAAAAAAAAAAQEBAQEBAQEBAQEBAAAAAAAAAAAAAAAAAAAAAAAAAAABAQEBAQEBAQEBAQEAAAAAAAAAAAAAAAAAAAAAAAAAAAEBAQEBAQEBAQEBAQAAAAAAAAAAAAAAAAAAAAAAAAAAAQEBAQEBAQEBAQEBAAAAAAAAAAAAAAAAAAAAAAAAAAABAQEBAQEBAQEBAQEAAAAAAAAAAAAAAAAAAAAAAAAAAAEBAQEBAQEBAQEBAQAAAAAAAAAAAAAAAAAAAQEBAQEBAQEBAQEBAQEBAQEBAAAAAAAAAAAAAAAAAAABAQEBAQEBAQEBAQEBAQEBAQEAAAAAAAAAAAAAAAAAAAEBAQEBAQEBAQEBAQEBAQEBAQAAAAAAAAAAAAAAAAAAAQEBAQEBAQEBAQEBAAAAAAAAAAAAAAAAAAAAAAAAAAABAQEBAQEBAQEBAQEAAAAAAAAAAAAAAAAAAAAAAAAAAAEBAQEBAQEBAQEBAQAAAAAAAAAAAAAAAAAAAQEBAQEBAQEBAQEBAQEBAQEBAAAAAAAAAAAAAAAAAAABAQEBAQEBAQEBAQEBAQEBAQEAAAAAAAAAAAAAAAAAAAEBAQEBAQEBAQEBAQEBAQEBAQAAAAAAAAAAAAAAAAAAAQEBAQEBAQEBAQEBAQEBAQEBAAAAAAAAAAAAAAAAAAABAQEBAQEBAQEBAQEBAQEBAQEAAAAAAAAAAAAAAAAAAAEBAQEBAQEBAQEBAQ==" + }, + "palette" : { + "originalArgb8888" : [ -265674 ], + "convertedRgb565" : [ -122 ] } }, "diagnostics" : [ ] @@ -492,14 +492,14 @@ "last_modified" : 1774359772437, "fingerprint" : "eeb7cc665386299403b7be1c272375d5077f3647c587f8033aa8c9275f840562", "metadata" : { - "palette" : { - "originalArgb8888" : [ -265674 ], - "convertedRgb565" : [ -122 ] - }, "tile" : { "width" : 32, "height" : 32, "paletteIndices" : "AQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAAAAAAAAAAABAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEAAAAAAAAAAAEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQAAAAAAAAAAAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAAAAAAAAAAABAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEAAAAAAAAAAAEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQAAAAAAAAAAAQEBAQEBAQEBAQEBAAAAAAAAAAAAAAAAAAAAAAAAAAABAQEBAQEBAQEBAQEAAAAAAAAAAAAAAAAAAAAAAAAAAAEBAQEBAQEBAQEBAQAAAAAAAAAAAAAAAAAAAAAAAAAAAQEBAQEBAQEBAQEBAAAAAAAAAAAAAAAAAAAAAAAAAAABAQEBAQEBAQEBAQEAAAAAAAAAAAAAAAAAAAAAAAAAAAEBAQEBAQEBAQEBAQAAAAAAAAAAAAAAAAAAAAAAAAAAAQEBAQEBAQEBAQEBAAAAAAAAAAAAAAAAAAAAAAAAAAABAQEBAQEBAQEBAQEAAAAAAAAAAAAAAAAAAAAAAAAAAAEBAQEBAQEBAQEBAQAAAAAAAAAAAAAAAAAAAQEBAQEBAQEBAQEBAQEBAQEBAAAAAAAAAAAAAAAAAAABAQEBAQEBAQEBAQEBAQEBAQEAAAAAAAAAAAAAAAAAAAEBAQEBAQEBAQEBAQEBAQEBAQAAAAAAAAAAAAAAAAAAAQEBAQEBAQEBAQEBAAAAAAAAAAAAAAAAAAAAAAAAAAABAQEBAQEBAQEBAQEAAAAAAAAAAAAAAAAAAAAAAAAAAAEBAQEBAQEBAQEBAQAAAAAAAAAAAAAAAAAAAQEBAQEBAQEBAQEBAQEBAQEBAAAAAAAAAAAAAAAAAAABAQEBAQEBAQEBAQEBAQEBAQEAAAAAAAAAAAAAAAAAAAEBAQEBAQEBAQEBAQEBAQEBAQAAAAAAAAAAAAAAAAAAAQEBAQEBAQEBAQEBAQEBAQEBAAAAAAAAAAAAAAAAAAABAQEBAQEBAQEBAQEBAQEBAQEAAAAAAAAAAAAAAAAAAAEBAQEBAQEBAQEBAQ==" + }, + "palette" : { + "originalArgb8888" : [ -265674 ], + "convertedRgb565" : [ -122 ] } }, "diagnostics" : [ ] @@ -510,14 +510,14 @@ "last_modified" : 1774359772438, "fingerprint" : "eeb7cc665386299403b7be1c272375d5077f3647c587f8033aa8c9275f840562", "metadata" : { - "palette" : { - "originalArgb8888" : [ -265674 ], - "convertedRgb565" : [ -122 ] - }, "tile" : { "width" : 32, "height" : 32, "paletteIndices" : "AQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAAAAAAAAAAABAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEAAAAAAAAAAAEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQAAAAAAAAAAAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAAAAAAAAAAABAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEAAAAAAAAAAAEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQAAAAAAAAAAAQEBAQEBAQEBAQEBAAAAAAAAAAAAAAAAAAAAAAAAAAABAQEBAQEBAQEBAQEAAAAAAAAAAAAAAAAAAAAAAAAAAAEBAQEBAQEBAQEBAQAAAAAAAAAAAAAAAAAAAAAAAAAAAQEBAQEBAQEBAQEBAAAAAAAAAAAAAAAAAAAAAAAAAAABAQEBAQEBAQEBAQEAAAAAAAAAAAAAAAAAAAAAAAAAAAEBAQEBAQEBAQEBAQAAAAAAAAAAAAAAAAAAAAAAAAAAAQEBAQEBAQEBAQEBAAAAAAAAAAAAAAAAAAAAAAAAAAABAQEBAQEBAQEBAQEAAAAAAAAAAAAAAAAAAAAAAAAAAAEBAQEBAQEBAQEBAQAAAAAAAAAAAAAAAAAAAQEBAQEBAQEBAQEBAQEBAQEBAAAAAAAAAAAAAAAAAAABAQEBAQEBAQEBAQEBAQEBAQEAAAAAAAAAAAAAAAAAAAEBAQEBAQEBAQEBAQEBAQEBAQAAAAAAAAAAAAAAAAAAAQEBAQEBAQEBAQEBAAAAAAAAAAAAAAAAAAAAAAAAAAABAQEBAQEBAQEBAQEAAAAAAAAAAAAAAAAAAAAAAAAAAAEBAQEBAQEBAQEBAQAAAAAAAAAAAAAAAAAAAQEBAQEBAQEBAQEBAQEBAQEBAAAAAAAAAAAAAAAAAAABAQEBAQEBAQEBAQEBAQEBAQEAAAAAAAAAAAAAAAAAAAEBAQEBAQEBAQEBAQEBAQEBAQAAAAAAAAAAAAAAAAAAAQEBAQEBAQEBAQEBAQEBAQEBAAAAAAAAAAAAAAAAAAABAQEBAQEBAQEBAQEBAQEBAQEAAAAAAAAAAAAAAAAAAAEBAQEBAQEBAQEBAQ==" + }, + "palette" : { + "originalArgb8888" : [ -265674 ], + "convertedRgb565" : [ -122 ] } }, "diagnostics" : [ ] @@ -528,14 +528,14 @@ "last_modified" : 1774359772439, "fingerprint" : "eeb7cc665386299403b7be1c272375d5077f3647c587f8033aa8c9275f840562", "metadata" : { - "palette" : { - "originalArgb8888" : [ -265674 ], - "convertedRgb565" : [ -122 ] - }, "tile" : { "width" : 32, "height" : 32, "paletteIndices" : "AQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAAAAAAAAAAABAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEAAAAAAAAAAAEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQAAAAAAAAAAAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAAAAAAAAAAABAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEAAAAAAAAAAAEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQAAAAAAAAAAAQEBAQEBAQEBAQEBAAAAAAAAAAAAAAAAAAAAAAAAAAABAQEBAQEBAQEBAQEAAAAAAAAAAAAAAAAAAAAAAAAAAAEBAQEBAQEBAQEBAQAAAAAAAAAAAAAAAAAAAAAAAAAAAQEBAQEBAQEBAQEBAAAAAAAAAAAAAAAAAAAAAAAAAAABAQEBAQEBAQEBAQEAAAAAAAAAAAAAAAAAAAAAAAAAAAEBAQEBAQEBAQEBAQAAAAAAAAAAAAAAAAAAAAAAAAAAAQEBAQEBAQEBAQEBAAAAAAAAAAAAAAAAAAAAAAAAAAABAQEBAQEBAQEBAQEAAAAAAAAAAAAAAAAAAAAAAAAAAAEBAQEBAQEBAQEBAQAAAAAAAAAAAAAAAAAAAQEBAQEBAQEBAQEBAQEBAQEBAAAAAAAAAAAAAAAAAAABAQEBAQEBAQEBAQEBAQEBAQEAAAAAAAAAAAAAAAAAAAEBAQEBAQEBAQEBAQEBAQEBAQAAAAAAAAAAAAAAAAAAAQEBAQEBAQEBAQEBAAAAAAAAAAAAAAAAAAAAAAAAAAABAQEBAQEBAQEBAQEAAAAAAAAAAAAAAAAAAAAAAAAAAAEBAQEBAQEBAQEBAQAAAAAAAAAAAAAAAAAAAQEBAQEBAQEBAQEBAQEBAQEBAAAAAAAAAAAAAAAAAAABAQEBAQEBAQEBAQEBAQEBAQEAAAAAAAAAAAAAAAAAAAEBAQEBAQEBAQEBAQEBAQEBAQAAAAAAAAAAAAAAAAAAAQEBAQEBAQEBAQEBAQEBAQEBAAAAAAAAAAAAAAAAAAABAQEBAQEBAQEBAQEBAQEBAQEAAAAAAAAAAAAAAAAAAAEBAQEBAQEBAQEBAQ==" + }, + "palette" : { + "originalArgb8888" : [ -265674 ], + "convertedRgb565" : [ -122 ] } }, "diagnostics" : [ ] @@ -546,14 +546,14 @@ "last_modified" : 1774359772441, "fingerprint" : "eeb7cc665386299403b7be1c272375d5077f3647c587f8033aa8c9275f840562", "metadata" : { - "palette" : { - "originalArgb8888" : [ -265674 ], - "convertedRgb565" : [ -122 ] - }, "tile" : { "width" : 32, "height" : 32, "paletteIndices" : "AQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAAAAAAAAAAABAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEAAAAAAAAAAAEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQAAAAAAAAAAAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAAAAAAAAAAABAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEAAAAAAAAAAAEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQAAAAAAAAAAAQEBAQEBAQEBAQEBAAAAAAAAAAAAAAAAAAAAAAAAAAABAQEBAQEBAQEBAQEAAAAAAAAAAAAAAAAAAAAAAAAAAAEBAQEBAQEBAQEBAQAAAAAAAAAAAAAAAAAAAAAAAAAAAQEBAQEBAQEBAQEBAAAAAAAAAAAAAAAAAAAAAAAAAAABAQEBAQEBAQEBAQEAAAAAAAAAAAAAAAAAAAAAAAAAAAEBAQEBAQEBAQEBAQAAAAAAAAAAAAAAAAAAAAAAAAAAAQEBAQEBAQEBAQEBAAAAAAAAAAAAAAAAAAAAAAAAAAABAQEBAQEBAQEBAQEAAAAAAAAAAAAAAAAAAAAAAAAAAAEBAQEBAQEBAQEBAQAAAAAAAAAAAAAAAAAAAQEBAQEBAQEBAQEBAQEBAQEBAAAAAAAAAAAAAAAAAAABAQEBAQEBAQEBAQEBAQEBAQEAAAAAAAAAAAAAAAAAAAEBAQEBAQEBAQEBAQEBAQEBAQAAAAAAAAAAAAAAAAAAAQEBAQEBAQEBAQEBAAAAAAAAAAAAAAAAAAAAAAAAAAABAQEBAQEBAQEBAQEAAAAAAAAAAAAAAAAAAAAAAAAAAAEBAQEBAQEBAQEBAQAAAAAAAAAAAAAAAAAAAQEBAQEBAQEBAQEBAQEBAQEBAAAAAAAAAAAAAAAAAAABAQEBAQEBAQEBAQEBAQEBAQEAAAAAAAAAAAAAAAAAAAEBAQEBAQEBAQEBAQEBAQEBAQAAAAAAAAAAAAAAAAAAAQEBAQEBAQEBAQEBAQEBAQEBAAAAAAAAAAAAAAAAAAABAQEBAQEBAQEBAQEBAQEBAQEAAAAAAAAAAAAAAAAAAAEBAQEBAQEBAQEBAQ==" + }, + "palette" : { + "originalArgb8888" : [ -265674 ], + "convertedRgb565" : [ -122 ] } }, "diagnostics" : [ ] @@ -564,14 +564,14 @@ "last_modified" : 1774359772442, "fingerprint" : "eeb7cc665386299403b7be1c272375d5077f3647c587f8033aa8c9275f840562", "metadata" : { - "palette" : { - "originalArgb8888" : [ -265674 ], - "convertedRgb565" : [ -122 ] - }, "tile" : { "width" : 32, "height" : 32, "paletteIndices" : "AQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAAAAAAAAAAABAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEAAAAAAAAAAAEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQAAAAAAAAAAAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAAAAAAAAAAABAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEAAAAAAAAAAAEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQAAAAAAAAAAAQEBAQEBAQEBAQEBAAAAAAAAAAAAAAAAAAAAAAAAAAABAQEBAQEBAQEBAQEAAAAAAAAAAAAAAAAAAAAAAAAAAAEBAQEBAQEBAQEBAQAAAAAAAAAAAAAAAAAAAAAAAAAAAQEBAQEBAQEBAQEBAAAAAAAAAAAAAAAAAAAAAAAAAAABAQEBAQEBAQEBAQEAAAAAAAAAAAAAAAAAAAAAAAAAAAEBAQEBAQEBAQEBAQAAAAAAAAAAAAAAAAAAAAAAAAAAAQEBAQEBAQEBAQEBAAAAAAAAAAAAAAAAAAAAAAAAAAABAQEBAQEBAQEBAQEAAAAAAAAAAAAAAAAAAAAAAAAAAAEBAQEBAQEBAQEBAQAAAAAAAAAAAAAAAAAAAQEBAQEBAQEBAQEBAQEBAQEBAAAAAAAAAAAAAAAAAAABAQEBAQEBAQEBAQEBAQEBAQEAAAAAAAAAAAAAAAAAAAEBAQEBAQEBAQEBAQEBAQEBAQAAAAAAAAAAAAAAAAAAAQEBAQEBAQEBAQEBAAAAAAAAAAAAAAAAAAAAAAAAAAABAQEBAQEBAQEBAQEAAAAAAAAAAAAAAAAAAAAAAAAAAAEBAQEBAQEBAQEBAQAAAAAAAAAAAAAAAAAAAQEBAQEBAQEBAQEBAQEBAQEBAAAAAAAAAAAAAAAAAAABAQEBAQEBAQEBAQEBAQEBAQEAAAAAAAAAAAAAAAAAAAEBAQEBAQEBAQEBAQEBAQEBAQAAAAAAAAAAAAAAAAAAAQEBAQEBAQEBAQEBAQEBAQEBAAAAAAAAAAAAAAAAAAABAQEBAQEBAQEBAQEBAQEBAQEAAAAAAAAAAAAAAAAAAAEBAQEBAQEBAQEBAQ==" + }, + "palette" : { + "originalArgb8888" : [ -265674 ], + "convertedRgb565" : [ -122 ] } }, "diagnostics" : [ ] @@ -582,14 +582,14 @@ "last_modified" : 1774359772443, "fingerprint" : "eeb7cc665386299403b7be1c272375d5077f3647c587f8033aa8c9275f840562", "metadata" : { - "palette" : { - "originalArgb8888" : [ -265674 ], - "convertedRgb565" : [ -122 ] - }, "tile" : { "width" : 32, "height" : 32, "paletteIndices" : "AQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAAAAAAAAAAABAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEAAAAAAAAAAAEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQAAAAAAAAAAAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAAAAAAAAAAABAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEAAAAAAAAAAAEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQAAAAAAAAAAAQEBAQEBAQEBAQEBAAAAAAAAAAAAAAAAAAAAAAAAAAABAQEBAQEBAQEBAQEAAAAAAAAAAAAAAAAAAAAAAAAAAAEBAQEBAQEBAQEBAQAAAAAAAAAAAAAAAAAAAAAAAAAAAQEBAQEBAQEBAQEBAAAAAAAAAAAAAAAAAAAAAAAAAAABAQEBAQEBAQEBAQEAAAAAAAAAAAAAAAAAAAAAAAAAAAEBAQEBAQEBAQEBAQAAAAAAAAAAAAAAAAAAAAAAAAAAAQEBAQEBAQEBAQEBAAAAAAAAAAAAAAAAAAAAAAAAAAABAQEBAQEBAQEBAQEAAAAAAAAAAAAAAAAAAAAAAAAAAAEBAQEBAQEBAQEBAQAAAAAAAAAAAAAAAAAAAQEBAQEBAQEBAQEBAQEBAQEBAAAAAAAAAAAAAAAAAAABAQEBAQEBAQEBAQEBAQEBAQEAAAAAAAAAAAAAAAAAAAEBAQEBAQEBAQEBAQEBAQEBAQAAAAAAAAAAAAAAAAAAAQEBAQEBAQEBAQEBAAAAAAAAAAAAAAAAAAAAAAAAAAABAQEBAQEBAQEBAQEAAAAAAAAAAAAAAAAAAAAAAAAAAAEBAQEBAQEBAQEBAQAAAAAAAAAAAAAAAAAAAQEBAQEBAQEBAQEBAQEBAQEBAAAAAAAAAAAAAAAAAAABAQEBAQEBAQEBAQEBAQEBAQEAAAAAAAAAAAAAAAAAAAEBAQEBAQEBAQEBAQEBAQEBAQAAAAAAAAAAAAAAAAAAAQEBAQEBAQEBAQEBAQEBAQEBAAAAAAAAAAAAAAAAAAABAQEBAQEBAQEBAQEBAQEBAQEAAAAAAAAAAAAAAAAAAAEBAQEBAQEBAQEBAQ==" + }, + "palette" : { + "originalArgb8888" : [ -265674 ], + "convertedRgb565" : [ -122 ] } }, "diagnostics" : [ ] @@ -600,14 +600,14 @@ "last_modified" : 1774359772444, "fingerprint" : "eeb7cc665386299403b7be1c272375d5077f3647c587f8033aa8c9275f840562", "metadata" : { - "palette" : { - "originalArgb8888" : [ -265674 ], - "convertedRgb565" : [ -122 ] - }, "tile" : { "width" : 32, "height" : 32, "paletteIndices" : "AQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAAAAAAAAAAABAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEAAAAAAAAAAAEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQAAAAAAAAAAAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAAAAAAAAAAABAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEAAAAAAAAAAAEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQAAAAAAAAAAAQEBAQEBAQEBAQEBAAAAAAAAAAAAAAAAAAAAAAAAAAABAQEBAQEBAQEBAQEAAAAAAAAAAAAAAAAAAAAAAAAAAAEBAQEBAQEBAQEBAQAAAAAAAAAAAAAAAAAAAAAAAAAAAQEBAQEBAQEBAQEBAAAAAAAAAAAAAAAAAAAAAAAAAAABAQEBAQEBAQEBAQEAAAAAAAAAAAAAAAAAAAAAAAAAAAEBAQEBAQEBAQEBAQAAAAAAAAAAAAAAAAAAAAAAAAAAAQEBAQEBAQEBAQEBAAAAAAAAAAAAAAAAAAAAAAAAAAABAQEBAQEBAQEBAQEAAAAAAAAAAAAAAAAAAAAAAAAAAAEBAQEBAQEBAQEBAQAAAAAAAAAAAAAAAAAAAQEBAQEBAQEBAQEBAQEBAQEBAAAAAAAAAAAAAAAAAAABAQEBAQEBAQEBAQEBAQEBAQEAAAAAAAAAAAAAAAAAAAEBAQEBAQEBAQEBAQEBAQEBAQAAAAAAAAAAAAAAAAAAAQEBAQEBAQEBAQEBAAAAAAAAAAAAAAAAAAAAAAAAAAABAQEBAQEBAQEBAQEAAAAAAAAAAAAAAAAAAAAAAAAAAAEBAQEBAQEBAQEBAQAAAAAAAAAAAAAAAAAAAQEBAQEBAQEBAQEBAQEBAQEBAAAAAAAAAAAAAAAAAAABAQEBAQEBAQEBAQEBAQEBAQEAAAAAAAAAAAAAAAAAAAEBAQEBAQEBAQEBAQEBAQEBAQAAAAAAAAAAAAAAAAAAAQEBAQEBAQEBAQEBAQEBAQEBAAAAAAAAAAAAAAAAAAABAQEBAQEBAQEBAQEBAQEBAQEAAAAAAAAAAAAAAAAAAAEBAQEBAQEBAQEBAQ==" + }, + "palette" : { + "originalArgb8888" : [ -265674 ], + "convertedRgb565" : [ -122 ] } }, "diagnostics" : [ ] @@ -618,14 +618,14 @@ "last_modified" : 1774359772445, "fingerprint" : "eeb7cc665386299403b7be1c272375d5077f3647c587f8033aa8c9275f840562", "metadata" : { - "palette" : { - "originalArgb8888" : [ -265674 ], - "convertedRgb565" : [ -122 ] - }, "tile" : { "width" : 32, "height" : 32, "paletteIndices" : "AQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAAAAAAAAAAABAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEAAAAAAAAAAAEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQAAAAAAAAAAAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAAAAAAAAAAABAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEAAAAAAAAAAAEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQAAAAAAAAAAAQEBAQEBAQEBAQEBAAAAAAAAAAAAAAAAAAAAAAAAAAABAQEBAQEBAQEBAQEAAAAAAAAAAAAAAAAAAAAAAAAAAAEBAQEBAQEBAQEBAQAAAAAAAAAAAAAAAAAAAAAAAAAAAQEBAQEBAQEBAQEBAAAAAAAAAAAAAAAAAAAAAAAAAAABAQEBAQEBAQEBAQEAAAAAAAAAAAAAAAAAAAAAAAAAAAEBAQEBAQEBAQEBAQAAAAAAAAAAAAAAAAAAAAAAAAAAAQEBAQEBAQEBAQEBAAAAAAAAAAAAAAAAAAAAAAAAAAABAQEBAQEBAQEBAQEAAAAAAAAAAAAAAAAAAAAAAAAAAAEBAQEBAQEBAQEBAQAAAAAAAAAAAAAAAAAAAQEBAQEBAQEBAQEBAQEBAQEBAAAAAAAAAAAAAAAAAAABAQEBAQEBAQEBAQEBAQEBAQEAAAAAAAAAAAAAAAAAAAEBAQEBAQEBAQEBAQEBAQEBAQAAAAAAAAAAAAAAAAAAAQEBAQEBAQEBAQEBAAAAAAAAAAAAAAAAAAAAAAAAAAABAQEBAQEBAQEBAQEAAAAAAAAAAAAAAAAAAAAAAAAAAAEBAQEBAQEBAQEBAQAAAAAAAAAAAAAAAAAAAQEBAQEBAQEBAQEBAQEBAQEBAAAAAAAAAAAAAAAAAAABAQEBAQEBAQEBAQEBAQEBAQEAAAAAAAAAAAAAAAAAAAEBAQEBAQEBAQEBAQEBAQEBAQAAAAAAAAAAAAAAAAAAAQEBAQEBAQEBAQEBAQEBAQEBAAAAAAAAAAAAAAAAAAABAQEBAQEBAQEBAQEBAQEBAQEAAAAAAAAAAAAAAAAAAAEBAQEBAQEBAQEBAQ==" + }, + "palette" : { + "originalArgb8888" : [ -265674 ], + "convertedRgb565" : [ -122 ] } }, "diagnostics" : [ ] @@ -636,14 +636,14 @@ "last_modified" : 1774359772448, "fingerprint" : "eeb7cc665386299403b7be1c272375d5077f3647c587f8033aa8c9275f840562", "metadata" : { - "palette" : { - "originalArgb8888" : [ -265674 ], - "convertedRgb565" : [ -122 ] - }, "tile" : { "width" : 32, "height" : 32, "paletteIndices" : "AQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAAAAAAAAAAABAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEAAAAAAAAAAAEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQAAAAAAAAAAAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAAAAAAAAAAABAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEAAAAAAAAAAAEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQAAAAAAAAAAAQEBAQEBAQEBAQEBAAAAAAAAAAAAAAAAAAAAAAAAAAABAQEBAQEBAQEBAQEAAAAAAAAAAAAAAAAAAAAAAAAAAAEBAQEBAQEBAQEBAQAAAAAAAAAAAAAAAAAAAAAAAAAAAQEBAQEBAQEBAQEBAAAAAAAAAAAAAAAAAAAAAAAAAAABAQEBAQEBAQEBAQEAAAAAAAAAAAAAAAAAAAAAAAAAAAEBAQEBAQEBAQEBAQAAAAAAAAAAAAAAAAAAAAAAAAAAAQEBAQEBAQEBAQEBAAAAAAAAAAAAAAAAAAAAAAAAAAABAQEBAQEBAQEBAQEAAAAAAAAAAAAAAAAAAAAAAAAAAAEBAQEBAQEBAQEBAQAAAAAAAAAAAAAAAAAAAQEBAQEBAQEBAQEBAQEBAQEBAAAAAAAAAAAAAAAAAAABAQEBAQEBAQEBAQEBAQEBAQEAAAAAAAAAAAAAAAAAAAEBAQEBAQEBAQEBAQEBAQEBAQAAAAAAAAAAAAAAAAAAAQEBAQEBAQEBAQEBAAAAAAAAAAAAAAAAAAAAAAAAAAABAQEBAQEBAQEBAQEAAAAAAAAAAAAAAAAAAAAAAAAAAAEBAQEBAQEBAQEBAQAAAAAAAAAAAAAAAAAAAQEBAQEBAQEBAQEBAQEBAQEBAAAAAAAAAAAAAAAAAAABAQEBAQEBAQEBAQEBAQEBAQEAAAAAAAAAAAAAAAAAAAEBAQEBAQEBAQEBAQEBAQEBAQAAAAAAAAAAAAAAAAAAAQEBAQEBAQEBAQEBAQEBAQEBAAAAAAAAAAAAAAAAAAABAQEBAQEBAQEBAQEBAQEBAQEAAAAAAAAAAAAAAAAAAAEBAQEBAQEBAQEBAQ==" + }, + "palette" : { + "originalArgb8888" : [ -265674 ], + "convertedRgb565" : [ -122 ] } }, "diagnostics" : [ ] @@ -654,14 +654,14 @@ "last_modified" : 1774359772449, "fingerprint" : "eeb7cc665386299403b7be1c272375d5077f3647c587f8033aa8c9275f840562", "metadata" : { - "palette" : { - "originalArgb8888" : [ -265674 ], - "convertedRgb565" : [ -122 ] - }, "tile" : { "width" : 32, "height" : 32, "paletteIndices" : "AQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAAAAAAAAAAABAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEAAAAAAAAAAAEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQAAAAAAAAAAAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAAAAAAAAAAABAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEAAAAAAAAAAAEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQAAAAAAAAAAAQEBAQEBAQEBAQEBAAAAAAAAAAAAAAAAAAAAAAAAAAABAQEBAQEBAQEBAQEAAAAAAAAAAAAAAAAAAAAAAAAAAAEBAQEBAQEBAQEBAQAAAAAAAAAAAAAAAAAAAAAAAAAAAQEBAQEBAQEBAQEBAAAAAAAAAAAAAAAAAAAAAAAAAAABAQEBAQEBAQEBAQEAAAAAAAAAAAAAAAAAAAAAAAAAAAEBAQEBAQEBAQEBAQAAAAAAAAAAAAAAAAAAAAAAAAAAAQEBAQEBAQEBAQEBAAAAAAAAAAAAAAAAAAAAAAAAAAABAQEBAQEBAQEBAQEAAAAAAAAAAAAAAAAAAAAAAAAAAAEBAQEBAQEBAQEBAQAAAAAAAAAAAAAAAAAAAQEBAQEBAQEBAQEBAQEBAQEBAAAAAAAAAAAAAAAAAAABAQEBAQEBAQEBAQEBAQEBAQEAAAAAAAAAAAAAAAAAAAEBAQEBAQEBAQEBAQEBAQEBAQAAAAAAAAAAAAAAAAAAAQEBAQEBAQEBAQEBAAAAAAAAAAAAAAAAAAAAAAAAAAABAQEBAQEBAQEBAQEAAAAAAAAAAAAAAAAAAAAAAAAAAAEBAQEBAQEBAQEBAQAAAAAAAAAAAAAAAAAAAQEBAQEBAQEBAQEBAQEBAQEBAAAAAAAAAAAAAAAAAAABAQEBAQEBAQEBAQEBAQEBAQEAAAAAAAAAAAAAAAAAAAEBAQEBAQEBAQEBAQEBAQEBAQAAAAAAAAAAAAAAAAAAAQEBAQEBAQEBAQEBAQEBAQEBAAAAAAAAAAAAAAAAAAABAQEBAQEBAQEBAQEBAQEBAQEAAAAAAAAAAAAAAAAAAAEBAQEBAQEBAQEBAQ==" + }, + "palette" : { + "originalArgb8888" : [ -265674 ], + "convertedRgb565" : [ -122 ] } }, "diagnostics" : [ ] @@ -672,14 +672,14 @@ "last_modified" : 1774359772450, "fingerprint" : "eeb7cc665386299403b7be1c272375d5077f3647c587f8033aa8c9275f840562", "metadata" : { - "palette" : { - "originalArgb8888" : [ -265674 ], - "convertedRgb565" : [ -122 ] - }, "tile" : { "width" : 32, "height" : 32, "paletteIndices" : "AQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAAAAAAAAAAABAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEAAAAAAAAAAAEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQAAAAAAAAAAAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAAAAAAAAAAABAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEAAAAAAAAAAAEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQAAAAAAAAAAAQEBAQEBAQEBAQEBAAAAAAAAAAAAAAAAAAAAAAAAAAABAQEBAQEBAQEBAQEAAAAAAAAAAAAAAAAAAAAAAAAAAAEBAQEBAQEBAQEBAQAAAAAAAAAAAAAAAAAAAAAAAAAAAQEBAQEBAQEBAQEBAAAAAAAAAAAAAAAAAAAAAAAAAAABAQEBAQEBAQEBAQEAAAAAAAAAAAAAAAAAAAAAAAAAAAEBAQEBAQEBAQEBAQAAAAAAAAAAAAAAAAAAAAAAAAAAAQEBAQEBAQEBAQEBAAAAAAAAAAAAAAAAAAAAAAAAAAABAQEBAQEBAQEBAQEAAAAAAAAAAAAAAAAAAAAAAAAAAAEBAQEBAQEBAQEBAQAAAAAAAAAAAAAAAAAAAQEBAQEBAQEBAQEBAQEBAQEBAAAAAAAAAAAAAAAAAAABAQEBAQEBAQEBAQEBAQEBAQEAAAAAAAAAAAAAAAAAAAEBAQEBAQEBAQEBAQEBAQEBAQAAAAAAAAAAAAAAAAAAAQEBAQEBAQEBAQEBAAAAAAAAAAAAAAAAAAAAAAAAAAABAQEBAQEBAQEBAQEAAAAAAAAAAAAAAAAAAAAAAAAAAAEBAQEBAQEBAQEBAQAAAAAAAAAAAAAAAAAAAQEBAQEBAQEBAQEBAQEBAQEBAAAAAAAAAAAAAAAAAAABAQEBAQEBAQEBAQEBAQEBAQEAAAAAAAAAAAAAAAAAAAEBAQEBAQEBAQEBAQEBAQEBAQAAAAAAAAAAAAAAAAAAAQEBAQEBAQEBAQEBAQEBAQEBAAAAAAAAAAAAAAAAAAABAQEBAQEBAQEBAQEBAQEBAQEAAAAAAAAAAAAAAAAAAAEBAQEBAQEBAQEBAQ==" + }, + "palette" : { + "originalArgb8888" : [ -265674 ], + "convertedRgb565" : [ -122 ] } }, "diagnostics" : [ ] @@ -690,14 +690,14 @@ "last_modified" : 1774359772452, "fingerprint" : "eeb7cc665386299403b7be1c272375d5077f3647c587f8033aa8c9275f840562", "metadata" : { - "palette" : { - "originalArgb8888" : [ -265674 ], - "convertedRgb565" : [ -122 ] - }, "tile" : { "width" : 32, "height" : 32, "paletteIndices" : "AQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAAAAAAAAAAABAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEAAAAAAAAAAAEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQAAAAAAAAAAAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAAAAAAAAAAABAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEAAAAAAAAAAAEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQAAAAAAAAAAAQEBAQEBAQEBAQEBAAAAAAAAAAAAAAAAAAAAAAAAAAABAQEBAQEBAQEBAQEAAAAAAAAAAAAAAAAAAAAAAAAAAAEBAQEBAQEBAQEBAQAAAAAAAAAAAAAAAAAAAAAAAAAAAQEBAQEBAQEBAQEBAAAAAAAAAAAAAAAAAAAAAAAAAAABAQEBAQEBAQEBAQEAAAAAAAAAAAAAAAAAAAAAAAAAAAEBAQEBAQEBAQEBAQAAAAAAAAAAAAAAAAAAAAAAAAAAAQEBAQEBAQEBAQEBAAAAAAAAAAAAAAAAAAAAAAAAAAABAQEBAQEBAQEBAQEAAAAAAAAAAAAAAAAAAAAAAAAAAAEBAQEBAQEBAQEBAQAAAAAAAAAAAAAAAAAAAQEBAQEBAQEBAQEBAQEBAQEBAAAAAAAAAAAAAAAAAAABAQEBAQEBAQEBAQEBAQEBAQEAAAAAAAAAAAAAAAAAAAEBAQEBAQEBAQEBAQEBAQEBAQAAAAAAAAAAAAAAAAAAAQEBAQEBAQEBAQEBAAAAAAAAAAAAAAAAAAAAAAAAAAABAQEBAQEBAQEBAQEAAAAAAAAAAAAAAAAAAAAAAAAAAAEBAQEBAQEBAQEBAQAAAAAAAAAAAAAAAAAAAQEBAQEBAQEBAQEBAQEBAQEBAAAAAAAAAAAAAAAAAAABAQEBAQEBAQEBAQEBAQEBAQEAAAAAAAAAAAAAAAAAAAEBAQEBAQEBAQEBAQEBAQEBAQAAAAAAAAAAAAAAAAAAAQEBAQEBAQEBAQEBAQEBAQEBAAAAAAAAAAAAAAAAAAABAQEBAQEBAQEBAQEBAQEBAQEAAAAAAAAAAAAAAAAAAAEBAQEBAQEBAQEBAQ==" + }, + "palette" : { + "originalArgb8888" : [ -265674 ], + "convertedRgb565" : [ -122 ] } }, "diagnostics" : [ ] @@ -708,14 +708,14 @@ "last_modified" : 1774359772453, "fingerprint" : "eeb7cc665386299403b7be1c272375d5077f3647c587f8033aa8c9275f840562", "metadata" : { - "palette" : { - "originalArgb8888" : [ -265674 ], - "convertedRgb565" : [ -122 ] - }, "tile" : { "width" : 32, "height" : 32, "paletteIndices" : "AQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAAAAAAAAAAABAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEAAAAAAAAAAAEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQAAAAAAAAAAAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAAAAAAAAAAABAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEAAAAAAAAAAAEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQAAAAAAAAAAAQEBAQEBAQEBAQEBAAAAAAAAAAAAAAAAAAAAAAAAAAABAQEBAQEBAQEBAQEAAAAAAAAAAAAAAAAAAAAAAAAAAAEBAQEBAQEBAQEBAQAAAAAAAAAAAAAAAAAAAAAAAAAAAQEBAQEBAQEBAQEBAAAAAAAAAAAAAAAAAAAAAAAAAAABAQEBAQEBAQEBAQEAAAAAAAAAAAAAAAAAAAAAAAAAAAEBAQEBAQEBAQEBAQAAAAAAAAAAAAAAAAAAAAAAAAAAAQEBAQEBAQEBAQEBAAAAAAAAAAAAAAAAAAAAAAAAAAABAQEBAQEBAQEBAQEAAAAAAAAAAAAAAAAAAAAAAAAAAAEBAQEBAQEBAQEBAQAAAAAAAAAAAAAAAAAAAQEBAQEBAQEBAQEBAQEBAQEBAAAAAAAAAAAAAAAAAAABAQEBAQEBAQEBAQEBAQEBAQEAAAAAAAAAAAAAAAAAAAEBAQEBAQEBAQEBAQEBAQEBAQAAAAAAAAAAAAAAAAAAAQEBAQEBAQEBAQEBAAAAAAAAAAAAAAAAAAAAAAAAAAABAQEBAQEBAQEBAQEAAAAAAAAAAAAAAAAAAAAAAAAAAAEBAQEBAQEBAQEBAQAAAAAAAAAAAAAAAAAAAQEBAQEBAQEBAQEBAQEBAQEBAAAAAAAAAAAAAAAAAAABAQEBAQEBAQEBAQEBAQEBAQEAAAAAAAAAAAAAAAAAAAEBAQEBAQEBAQEBAQEBAQEBAQAAAAAAAAAAAAAAAAAAAQEBAQEBAQEBAQEBAQEBAQEBAAAAAAAAAAAAAAAAAAABAQEBAQEBAQEBAQEBAQEBAQEAAAAAAAAAAAAAAAAAAAEBAQEBAQEBAQEBAQ==" + }, + "palette" : { + "originalArgb8888" : [ -265674 ], + "convertedRgb565" : [ -122 ] } }, "diagnostics" : [ ] @@ -726,14 +726,14 @@ "last_modified" : 1774359772454, "fingerprint" : "eeb7cc665386299403b7be1c272375d5077f3647c587f8033aa8c9275f840562", "metadata" : { - "palette" : { - "originalArgb8888" : [ -265674 ], - "convertedRgb565" : [ -122 ] - }, "tile" : { "width" : 32, "height" : 32, "paletteIndices" : "AQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAAAAAAAAAAABAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEAAAAAAAAAAAEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQAAAAAAAAAAAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAAAAAAAAAAABAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEAAAAAAAAAAAEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQAAAAAAAAAAAQEBAQEBAQEBAQEBAAAAAAAAAAAAAAAAAAAAAAAAAAABAQEBAQEBAQEBAQEAAAAAAAAAAAAAAAAAAAAAAAAAAAEBAQEBAQEBAQEBAQAAAAAAAAAAAAAAAAAAAAAAAAAAAQEBAQEBAQEBAQEBAAAAAAAAAAAAAAAAAAAAAAAAAAABAQEBAQEBAQEBAQEAAAAAAAAAAAAAAAAAAAAAAAAAAAEBAQEBAQEBAQEBAQAAAAAAAAAAAAAAAAAAAAAAAAAAAQEBAQEBAQEBAQEBAAAAAAAAAAAAAAAAAAAAAAAAAAABAQEBAQEBAQEBAQEAAAAAAAAAAAAAAAAAAAAAAAAAAAEBAQEBAQEBAQEBAQAAAAAAAAAAAAAAAAAAAQEBAQEBAQEBAQEBAQEBAQEBAAAAAAAAAAAAAAAAAAABAQEBAQEBAQEBAQEBAQEBAQEAAAAAAAAAAAAAAAAAAAEBAQEBAQEBAQEBAQEBAQEBAQAAAAAAAAAAAAAAAAAAAQEBAQEBAQEBAQEBAAAAAAAAAAAAAAAAAAAAAAAAAAABAQEBAQEBAQEBAQEAAAAAAAAAAAAAAAAAAAAAAAAAAAEBAQEBAQEBAQEBAQAAAAAAAAAAAAAAAAAAAQEBAQEBAQEBAQEBAQEBAQEBAAAAAAAAAAAAAAAAAAABAQEBAQEBAQEBAQEBAQEBAQEAAAAAAAAAAAAAAAAAAAEBAQEBAQEBAQEBAQEBAQEBAQAAAAAAAAAAAAAAAAAAAQEBAQEBAQEBAQEBAQEBAQEBAAAAAAAAAAAAAAAAAAABAQEBAQEBAQEBAQEBAQEBAQEAAAAAAAAAAAAAAAAAAAEBAQEBAQEBAQEBAQ==" + }, + "palette" : { + "originalArgb8888" : [ -265674 ], + "convertedRgb565" : [ -122 ] } }, "diagnostics" : [ ] @@ -744,14 +744,14 @@ "last_modified" : 1774359772455, "fingerprint" : "eeb7cc665386299403b7be1c272375d5077f3647c587f8033aa8c9275f840562", "metadata" : { - "palette" : { - "originalArgb8888" : [ -265674 ], - "convertedRgb565" : [ -122 ] - }, "tile" : { "width" : 32, "height" : 32, "paletteIndices" : "AQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAAAAAAAAAAABAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEAAAAAAAAAAAEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQAAAAAAAAAAAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAAAAAAAAAAABAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEAAAAAAAAAAAEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQAAAAAAAAAAAQEBAQEBAQEBAQEBAAAAAAAAAAAAAAAAAAAAAAAAAAABAQEBAQEBAQEBAQEAAAAAAAAAAAAAAAAAAAAAAAAAAAEBAQEBAQEBAQEBAQAAAAAAAAAAAAAAAAAAAAAAAAAAAQEBAQEBAQEBAQEBAAAAAAAAAAAAAAAAAAAAAAAAAAABAQEBAQEBAQEBAQEAAAAAAAAAAAAAAAAAAAAAAAAAAAEBAQEBAQEBAQEBAQAAAAAAAAAAAAAAAAAAAAAAAAAAAQEBAQEBAQEBAQEBAAAAAAAAAAAAAAAAAAAAAAAAAAABAQEBAQEBAQEBAQEAAAAAAAAAAAAAAAAAAAAAAAAAAAEBAQEBAQEBAQEBAQAAAAAAAAAAAAAAAAAAAQEBAQEBAQEBAQEBAQEBAQEBAAAAAAAAAAAAAAAAAAABAQEBAQEBAQEBAQEBAQEBAQEAAAAAAAAAAAAAAAAAAAEBAQEBAQEBAQEBAQEBAQEBAQAAAAAAAAAAAAAAAAAAAQEBAQEBAQEBAQEBAAAAAAAAAAAAAAAAAAAAAAAAAAABAQEBAQEBAQEBAQEAAAAAAAAAAAAAAAAAAAAAAAAAAAEBAQEBAQEBAQEBAQAAAAAAAAAAAAAAAAAAAQEBAQEBAQEBAQEBAQEBAQEBAAAAAAAAAAAAAAAAAAABAQEBAQEBAQEBAQEBAQEBAQEAAAAAAAAAAAAAAAAAAAEBAQEBAQEBAQEBAQEBAQEBAQAAAAAAAAAAAAAAAAAAAQEBAQEBAQEBAQEBAQEBAQEBAAAAAAAAAAAAAAAAAAABAQEBAQEBAQEBAQEBAQEBAQEAAAAAAAAAAAAAAAAAAAEBAQEBAQEBAQEBAQ==" + }, + "palette" : { + "originalArgb8888" : [ -265674 ], + "convertedRgb565" : [ -122 ] } }, "diagnostics" : [ ] @@ -762,14 +762,14 @@ "last_modified" : 1774359772456, "fingerprint" : "eeb7cc665386299403b7be1c272375d5077f3647c587f8033aa8c9275f840562", "metadata" : { - "palette" : { - "originalArgb8888" : [ -265674 ], - "convertedRgb565" : [ -122 ] - }, "tile" : { "width" : 32, "height" : 32, "paletteIndices" : "AQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAAAAAAAAAAABAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEAAAAAAAAAAAEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQAAAAAAAAAAAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAAAAAAAAAAABAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEAAAAAAAAAAAEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQAAAAAAAAAAAQEBAQEBAQEBAQEBAAAAAAAAAAAAAAAAAAAAAAAAAAABAQEBAQEBAQEBAQEAAAAAAAAAAAAAAAAAAAAAAAAAAAEBAQEBAQEBAQEBAQAAAAAAAAAAAAAAAAAAAAAAAAAAAQEBAQEBAQEBAQEBAAAAAAAAAAAAAAAAAAAAAAAAAAABAQEBAQEBAQEBAQEAAAAAAAAAAAAAAAAAAAAAAAAAAAEBAQEBAQEBAQEBAQAAAAAAAAAAAAAAAAAAAAAAAAAAAQEBAQEBAQEBAQEBAAAAAAAAAAAAAAAAAAAAAAAAAAABAQEBAQEBAQEBAQEAAAAAAAAAAAAAAAAAAAAAAAAAAAEBAQEBAQEBAQEBAQAAAAAAAAAAAAAAAAAAAQEBAQEBAQEBAQEBAQEBAQEBAAAAAAAAAAAAAAAAAAABAQEBAQEBAQEBAQEBAQEBAQEAAAAAAAAAAAAAAAAAAAEBAQEBAQEBAQEBAQEBAQEBAQAAAAAAAAAAAAAAAAAAAQEBAQEBAQEBAQEBAAAAAAAAAAAAAAAAAAAAAAAAAAABAQEBAQEBAQEBAQEAAAAAAAAAAAAAAAAAAAAAAAAAAAEBAQEBAQEBAQEBAQAAAAAAAAAAAAAAAAAAAQEBAQEBAQEBAQEBAQEBAQEBAAAAAAAAAAAAAAAAAAABAQEBAQEBAQEBAQEBAQEBAQEAAAAAAAAAAAAAAAAAAAEBAQEBAQEBAQEBAQEBAQEBAQAAAAAAAAAAAAAAAAAAAQEBAQEBAQEBAQEBAQEBAQEBAAAAAAAAAAAAAAAAAAABAQEBAQEBAQEBAQEBAQEBAQEAAAAAAAAAAAAAAAAAAAEBAQEBAQEBAQEBAQ==" + }, + "palette" : { + "originalArgb8888" : [ -265674 ], + "convertedRgb565" : [ -122 ] } }, "diagnostics" : [ ] @@ -780,14 +780,14 @@ "last_modified" : 1774359772458, "fingerprint" : "eeb7cc665386299403b7be1c272375d5077f3647c587f8033aa8c9275f840562", "metadata" : { - "palette" : { - "originalArgb8888" : [ -265674 ], - "convertedRgb565" : [ -122 ] - }, "tile" : { "width" : 32, "height" : 32, "paletteIndices" : "AQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAAAAAAAAAAABAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEAAAAAAAAAAAEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQAAAAAAAAAAAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAAAAAAAAAAABAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEAAAAAAAAAAAEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQAAAAAAAAAAAQEBAQEBAQEBAQEBAAAAAAAAAAAAAAAAAAAAAAAAAAABAQEBAQEBAQEBAQEAAAAAAAAAAAAAAAAAAAAAAAAAAAEBAQEBAQEBAQEBAQAAAAAAAAAAAAAAAAAAAAAAAAAAAQEBAQEBAQEBAQEBAAAAAAAAAAAAAAAAAAAAAAAAAAABAQEBAQEBAQEBAQEAAAAAAAAAAAAAAAAAAAAAAAAAAAEBAQEBAQEBAQEBAQAAAAAAAAAAAAAAAAAAAAAAAAAAAQEBAQEBAQEBAQEBAAAAAAAAAAAAAAAAAAAAAAAAAAABAQEBAQEBAQEBAQEAAAAAAAAAAAAAAAAAAAAAAAAAAAEBAQEBAQEBAQEBAQAAAAAAAAAAAAAAAAAAAQEBAQEBAQEBAQEBAQEBAQEBAAAAAAAAAAAAAAAAAAABAQEBAQEBAQEBAQEBAQEBAQEAAAAAAAAAAAAAAAAAAAEBAQEBAQEBAQEBAQEBAQEBAQAAAAAAAAAAAAAAAAAAAQEBAQEBAQEBAQEBAAAAAAAAAAAAAAAAAAAAAAAAAAABAQEBAQEBAQEBAQEAAAAAAAAAAAAAAAAAAAAAAAAAAAEBAQEBAQEBAQEBAQAAAAAAAAAAAAAAAAAAAQEBAQEBAQEBAQEBAQEBAQEBAAAAAAAAAAAAAAAAAAABAQEBAQEBAQEBAQEBAQEBAQEAAAAAAAAAAAAAAAAAAAEBAQEBAQEBAQEBAQEBAQEBAQAAAAAAAAAAAAAAAAAAAQEBAQEBAQEBAQEBAQEBAQEBAAAAAAAAAAAAAAAAAAABAQEBAQEBAQEBAQEBAQEBAQEAAAAAAAAAAAAAAAAAAAEBAQEBAQEBAQEBAQ==" + }, + "palette" : { + "originalArgb8888" : [ -265674 ], + "convertedRgb565" : [ -122 ] } }, "diagnostics" : [ ] @@ -798,14 +798,14 @@ "last_modified" : 1774359772459, "fingerprint" : "eeb7cc665386299403b7be1c272375d5077f3647c587f8033aa8c9275f840562", "metadata" : { - "palette" : { - "originalArgb8888" : [ -265674 ], - "convertedRgb565" : [ -122 ] - }, "tile" : { "width" : 32, "height" : 32, "paletteIndices" : "AQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAAAAAAAAAAABAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEAAAAAAAAAAAEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQAAAAAAAAAAAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAAAAAAAAAAABAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEAAAAAAAAAAAEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQAAAAAAAAAAAQEBAQEBAQEBAQEBAAAAAAAAAAAAAAAAAAAAAAAAAAABAQEBAQEBAQEBAQEAAAAAAAAAAAAAAAAAAAAAAAAAAAEBAQEBAQEBAQEBAQAAAAAAAAAAAAAAAAAAAAAAAAAAAQEBAQEBAQEBAQEBAAAAAAAAAAAAAAAAAAAAAAAAAAABAQEBAQEBAQEBAQEAAAAAAAAAAAAAAAAAAAAAAAAAAAEBAQEBAQEBAQEBAQAAAAAAAAAAAAAAAAAAAAAAAAAAAQEBAQEBAQEBAQEBAAAAAAAAAAAAAAAAAAAAAAAAAAABAQEBAQEBAQEBAQEAAAAAAAAAAAAAAAAAAAAAAAAAAAEBAQEBAQEBAQEBAQAAAAAAAAAAAAAAAAAAAQEBAQEBAQEBAQEBAQEBAQEBAAAAAAAAAAAAAAAAAAABAQEBAQEBAQEBAQEBAQEBAQEAAAAAAAAAAAAAAAAAAAEBAQEBAQEBAQEBAQEBAQEBAQAAAAAAAAAAAAAAAAAAAQEBAQEBAQEBAQEBAAAAAAAAAAAAAAAAAAAAAAAAAAABAQEBAQEBAQEBAQEAAAAAAAAAAAAAAAAAAAAAAAAAAAEBAQEBAQEBAQEBAQAAAAAAAAAAAAAAAAAAAQEBAQEBAQEBAQEBAQEBAQEBAAAAAAAAAAAAAAAAAAABAQEBAQEBAQEBAQEBAQEBAQEAAAAAAAAAAAAAAAAAAAEBAQEBAQEBAQEBAQEBAQEBAQAAAAAAAAAAAAAAAAAAAQEBAQEBAQEBAQEBAQEBAQEBAAAAAAAAAAAAAAAAAAABAQEBAQEBAQEBAQEBAQEBAQEAAAAAAAAAAAAAAAAAAAEBAQEBAQEBAQEBAQ==" + }, + "palette" : { + "originalArgb8888" : [ -265674 ], + "convertedRgb565" : [ -122 ] } }, "diagnostics" : [ ] @@ -816,14 +816,14 @@ "last_modified" : 1774359772460, "fingerprint" : "eeb7cc665386299403b7be1c272375d5077f3647c587f8033aa8c9275f840562", "metadata" : { - "palette" : { - "originalArgb8888" : [ -265674 ], - "convertedRgb565" : [ -122 ] - }, "tile" : { "width" : 32, "height" : 32, "paletteIndices" : "AQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAAAAAAAAAAABAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEAAAAAAAAAAAEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQAAAAAAAAAAAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAAAAAAAAAAABAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEAAAAAAAAAAAEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQAAAAAAAAAAAQEBAQEBAQEBAQEBAAAAAAAAAAAAAAAAAAAAAAAAAAABAQEBAQEBAQEBAQEAAAAAAAAAAAAAAAAAAAAAAAAAAAEBAQEBAQEBAQEBAQAAAAAAAAAAAAAAAAAAAAAAAAAAAQEBAQEBAQEBAQEBAAAAAAAAAAAAAAAAAAAAAAAAAAABAQEBAQEBAQEBAQEAAAAAAAAAAAAAAAAAAAAAAAAAAAEBAQEBAQEBAQEBAQAAAAAAAAAAAAAAAAAAAAAAAAAAAQEBAQEBAQEBAQEBAAAAAAAAAAAAAAAAAAAAAAAAAAABAQEBAQEBAQEBAQEAAAAAAAAAAAAAAAAAAAAAAAAAAAEBAQEBAQEBAQEBAQAAAAAAAAAAAAAAAAAAAQEBAQEBAQEBAQEBAQEBAQEBAAAAAAAAAAAAAAAAAAABAQEBAQEBAQEBAQEBAQEBAQEAAAAAAAAAAAAAAAAAAAEBAQEBAQEBAQEBAQEBAQEBAQAAAAAAAAAAAAAAAAAAAQEBAQEBAQEBAQEBAAAAAAAAAAAAAAAAAAAAAAAAAAABAQEBAQEBAQEBAQEAAAAAAAAAAAAAAAAAAAAAAAAAAAEBAQEBAQEBAQEBAQAAAAAAAAAAAAAAAAAAAQEBAQEBAQEBAQEBAQEBAQEBAAAAAAAAAAAAAAAAAAABAQEBAQEBAQEBAQEBAQEBAQEAAAAAAAAAAAAAAAAAAAEBAQEBAQEBAQEBAQEBAQEBAQAAAAAAAAAAAAAAAAAAAQEBAQEBAQEBAQEBAQEBAQEBAAAAAAAAAAAAAAAAAAABAQEBAQEBAQEBAQEBAQEBAQEAAAAAAAAAAAAAAAAAAAEBAQEBAQEBAQEBAQ==" + }, + "palette" : { + "originalArgb8888" : [ -265674 ], + "convertedRgb565" : [ -122 ] } }, "diagnostics" : [ ] @@ -834,14 +834,14 @@ "last_modified" : 1774359772461, "fingerprint" : "eeb7cc665386299403b7be1c272375d5077f3647c587f8033aa8c9275f840562", "metadata" : { - "palette" : { - "originalArgb8888" : [ -265674 ], - "convertedRgb565" : [ -122 ] - }, "tile" : { "width" : 32, "height" : 32, "paletteIndices" : "AQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAAAAAAAAAAABAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEAAAAAAAAAAAEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQAAAAAAAAAAAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAAAAAAAAAAABAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEAAAAAAAAAAAEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQAAAAAAAAAAAQEBAQEBAQEBAQEBAAAAAAAAAAAAAAAAAAAAAAAAAAABAQEBAQEBAQEBAQEAAAAAAAAAAAAAAAAAAAAAAAAAAAEBAQEBAQEBAQEBAQAAAAAAAAAAAAAAAAAAAAAAAAAAAQEBAQEBAQEBAQEBAAAAAAAAAAAAAAAAAAAAAAAAAAABAQEBAQEBAQEBAQEAAAAAAAAAAAAAAAAAAAAAAAAAAAEBAQEBAQEBAQEBAQAAAAAAAAAAAAAAAAAAAAAAAAAAAQEBAQEBAQEBAQEBAAAAAAAAAAAAAAAAAAAAAAAAAAABAQEBAQEBAQEBAQEAAAAAAAAAAAAAAAAAAAAAAAAAAAEBAQEBAQEBAQEBAQAAAAAAAAAAAAAAAAAAAQEBAQEBAQEBAQEBAQEBAQEBAAAAAAAAAAAAAAAAAAABAQEBAQEBAQEBAQEBAQEBAQEAAAAAAAAAAAAAAAAAAAEBAQEBAQEBAQEBAQEBAQEBAQAAAAAAAAAAAAAAAAAAAQEBAQEBAQEBAQEBAAAAAAAAAAAAAAAAAAAAAAAAAAABAQEBAQEBAQEBAQEAAAAAAAAAAAAAAAAAAAAAAAAAAAEBAQEBAQEBAQEBAQAAAAAAAAAAAAAAAAAAAQEBAQEBAQEBAQEBAQEBAQEBAAAAAAAAAAAAAAAAAAABAQEBAQEBAQEBAQEBAQEBAQEAAAAAAAAAAAAAAAAAAAEBAQEBAQEBAQEBAQEBAQEBAQAAAAAAAAAAAAAAAAAAAQEBAQEBAQEBAQEBAQEBAQEBAAAAAAAAAAAAAAAAAAABAQEBAQEBAQEBAQEBAQEBAQEAAAAAAAAAAAAAAAAAAAEBAQEBAQEBAQEBAQ==" + }, + "palette" : { + "originalArgb8888" : [ -265674 ], + "convertedRgb565" : [ -122 ] } }, "diagnostics" : [ ] @@ -852,14 +852,14 @@ "last_modified" : 1774359772463, "fingerprint" : "eeb7cc665386299403b7be1c272375d5077f3647c587f8033aa8c9275f840562", "metadata" : { - "palette" : { - "originalArgb8888" : [ -265674 ], - "convertedRgb565" : [ -122 ] - }, "tile" : { "width" : 32, "height" : 32, "paletteIndices" : "AQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAAAAAAAAAAABAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEAAAAAAAAAAAEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQAAAAAAAAAAAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAAAAAAAAAAABAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEAAAAAAAAAAAEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQAAAAAAAAAAAQEBAQEBAQEBAQEBAAAAAAAAAAAAAAAAAAAAAAAAAAABAQEBAQEBAQEBAQEAAAAAAAAAAAAAAAAAAAAAAAAAAAEBAQEBAQEBAQEBAQAAAAAAAAAAAAAAAAAAAAAAAAAAAQEBAQEBAQEBAQEBAAAAAAAAAAAAAAAAAAAAAAAAAAABAQEBAQEBAQEBAQEAAAAAAAAAAAAAAAAAAAAAAAAAAAEBAQEBAQEBAQEBAQAAAAAAAAAAAAAAAAAAAAAAAAAAAQEBAQEBAQEBAQEBAAAAAAAAAAAAAAAAAAAAAAAAAAABAQEBAQEBAQEBAQEAAAAAAAAAAAAAAAAAAAAAAAAAAAEBAQEBAQEBAQEBAQAAAAAAAAAAAAAAAAAAAQEBAQEBAQEBAQEBAQEBAQEBAAAAAAAAAAAAAAAAAAABAQEBAQEBAQEBAQEBAQEBAQEAAAAAAAAAAAAAAAAAAAEBAQEBAQEBAQEBAQEBAQEBAQAAAAAAAAAAAAAAAAAAAQEBAQEBAQEBAQEBAAAAAAAAAAAAAAAAAAAAAAAAAAABAQEBAQEBAQEBAQEAAAAAAAAAAAAAAAAAAAAAAAAAAAEBAQEBAQEBAQEBAQAAAAAAAAAAAAAAAAAAAQEBAQEBAQEBAQEBAQEBAQEBAAAAAAAAAAAAAAAAAAABAQEBAQEBAQEBAQEBAQEBAQEAAAAAAAAAAAAAAAAAAAEBAQEBAQEBAQEBAQEBAQEBAQAAAAAAAAAAAAAAAAAAAQEBAQEBAQEBAQEBAQEBAQEBAAAAAAAAAAAAAAAAAAABAQEBAQEBAQEBAQEBAQEBAQEAAAAAAAAAAAAAAAAAAAEBAQEBAQEBAQEBAQ==" + }, + "palette" : { + "originalArgb8888" : [ -265674 ], + "convertedRgb565" : [ -122 ] } }, "diagnostics" : [ ] @@ -870,14 +870,14 @@ "last_modified" : 1774359772464, "fingerprint" : "eeb7cc665386299403b7be1c272375d5077f3647c587f8033aa8c9275f840562", "metadata" : { - "palette" : { - "originalArgb8888" : [ -265674 ], - "convertedRgb565" : [ -122 ] - }, "tile" : { "width" : 32, "height" : 32, "paletteIndices" : "AQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAAAAAAAAAAABAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEAAAAAAAAAAAEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQAAAAAAAAAAAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAAAAAAAAAAABAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEAAAAAAAAAAAEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQAAAAAAAAAAAQEBAQEBAQEBAQEBAAAAAAAAAAAAAAAAAAAAAAAAAAABAQEBAQEBAQEBAQEAAAAAAAAAAAAAAAAAAAAAAAAAAAEBAQEBAQEBAQEBAQAAAAAAAAAAAAAAAAAAAAAAAAAAAQEBAQEBAQEBAQEBAAAAAAAAAAAAAAAAAAAAAAAAAAABAQEBAQEBAQEBAQEAAAAAAAAAAAAAAAAAAAAAAAAAAAEBAQEBAQEBAQEBAQAAAAAAAAAAAAAAAAAAAAAAAAAAAQEBAQEBAQEBAQEBAAAAAAAAAAAAAAAAAAAAAAAAAAABAQEBAQEBAQEBAQEAAAAAAAAAAAAAAAAAAAAAAAAAAAEBAQEBAQEBAQEBAQAAAAAAAAAAAAAAAAAAAQEBAQEBAQEBAQEBAQEBAQEBAAAAAAAAAAAAAAAAAAABAQEBAQEBAQEBAQEBAQEBAQEAAAAAAAAAAAAAAAAAAAEBAQEBAQEBAQEBAQEBAQEBAQAAAAAAAAAAAAAAAAAAAQEBAQEBAQEBAQEBAAAAAAAAAAAAAAAAAAAAAAAAAAABAQEBAQEBAQEBAQEAAAAAAAAAAAAAAAAAAAAAAAAAAAEBAQEBAQEBAQEBAQAAAAAAAAAAAAAAAAAAAQEBAQEBAQEBAQEBAQEBAQEBAAAAAAAAAAAAAAAAAAABAQEBAQEBAQEBAQEBAQEBAQEAAAAAAAAAAAAAAAAAAAEBAQEBAQEBAQEBAQEBAQEBAQAAAAAAAAAAAAAAAAAAAQEBAQEBAQEBAQEBAQEBAQEBAAAAAAAAAAAAAAAAAAABAQEBAQEBAQEBAQEBAQEBAQEAAAAAAAAAAAAAAAAAAAEBAQEBAQEBAQEBAQ==" + }, + "palette" : { + "originalArgb8888" : [ -265674 ], + "convertedRgb565" : [ -122 ] } }, "diagnostics" : [ ] @@ -888,14 +888,14 @@ "last_modified" : 1774359772465, "fingerprint" : "eeb7cc665386299403b7be1c272375d5077f3647c587f8033aa8c9275f840562", "metadata" : { - "palette" : { - "originalArgb8888" : [ -265674 ], - "convertedRgb565" : [ -122 ] - }, "tile" : { "width" : 32, "height" : 32, "paletteIndices" : "AQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAAAAAAAAAAABAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEAAAAAAAAAAAEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQAAAAAAAAAAAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAAAAAAAAAAABAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEAAAAAAAAAAAEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQAAAAAAAAAAAQEBAQEBAQEBAQEBAAAAAAAAAAAAAAAAAAAAAAAAAAABAQEBAQEBAQEBAQEAAAAAAAAAAAAAAAAAAAAAAAAAAAEBAQEBAQEBAQEBAQAAAAAAAAAAAAAAAAAAAAAAAAAAAQEBAQEBAQEBAQEBAAAAAAAAAAAAAAAAAAAAAAAAAAABAQEBAQEBAQEBAQEAAAAAAAAAAAAAAAAAAAAAAAAAAAEBAQEBAQEBAQEBAQAAAAAAAAAAAAAAAAAAAAAAAAAAAQEBAQEBAQEBAQEBAAAAAAAAAAAAAAAAAAAAAAAAAAABAQEBAQEBAQEBAQEAAAAAAAAAAAAAAAAAAAAAAAAAAAEBAQEBAQEBAQEBAQAAAAAAAAAAAAAAAAAAAQEBAQEBAQEBAQEBAQEBAQEBAAAAAAAAAAAAAAAAAAABAQEBAQEBAQEBAQEBAQEBAQEAAAAAAAAAAAAAAAAAAAEBAQEBAQEBAQEBAQEBAQEBAQAAAAAAAAAAAAAAAAAAAQEBAQEBAQEBAQEBAAAAAAAAAAAAAAAAAAAAAAAAAAABAQEBAQEBAQEBAQEAAAAAAAAAAAAAAAAAAAAAAAAAAAEBAQEBAQEBAQEBAQAAAAAAAAAAAAAAAAAAAQEBAQEBAQEBAQEBAQEBAQEBAAAAAAAAAAAAAAAAAAABAQEBAQEBAQEBAQEBAQEBAQEAAAAAAAAAAAAAAAAAAAEBAQEBAQEBAQEBAQEBAQEBAQAAAAAAAAAAAAAAAAAAAQEBAQEBAQEBAQEBAQEBAQEBAAAAAAAAAAAAAAAAAAABAQEBAQEBAQEBAQEBAQEBAQEAAAAAAAAAAAAAAAAAAAEBAQEBAQEBAQEBAQ==" + }, + "palette" : { + "originalArgb8888" : [ -265674 ], + "convertedRgb565" : [ -122 ] } }, "diagnostics" : [ ] @@ -906,14 +906,14 @@ "last_modified" : 1774359772467, "fingerprint" : "eeb7cc665386299403b7be1c272375d5077f3647c587f8033aa8c9275f840562", "metadata" : { - "palette" : { - "originalArgb8888" : [ -265674 ], - "convertedRgb565" : [ -122 ] - }, "tile" : { "width" : 32, "height" : 32, "paletteIndices" : "AQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAAAAAAAAAAABAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEAAAAAAAAAAAEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQAAAAAAAAAAAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAAAAAAAAAAABAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEAAAAAAAAAAAEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQAAAAAAAAAAAQEBAQEBAQEBAQEBAAAAAAAAAAAAAAAAAAAAAAAAAAABAQEBAQEBAQEBAQEAAAAAAAAAAAAAAAAAAAAAAAAAAAEBAQEBAQEBAQEBAQAAAAAAAAAAAAAAAAAAAAAAAAAAAQEBAQEBAQEBAQEBAAAAAAAAAAAAAAAAAAAAAAAAAAABAQEBAQEBAQEBAQEAAAAAAAAAAAAAAAAAAAAAAAAAAAEBAQEBAQEBAQEBAQAAAAAAAAAAAAAAAAAAAAAAAAAAAQEBAQEBAQEBAQEBAAAAAAAAAAAAAAAAAAAAAAAAAAABAQEBAQEBAQEBAQEAAAAAAAAAAAAAAAAAAAAAAAAAAAEBAQEBAQEBAQEBAQAAAAAAAAAAAAAAAAAAAQEBAQEBAQEBAQEBAQEBAQEBAAAAAAAAAAAAAAAAAAABAQEBAQEBAQEBAQEBAQEBAQEAAAAAAAAAAAAAAAAAAAEBAQEBAQEBAQEBAQEBAQEBAQAAAAAAAAAAAAAAAAAAAQEBAQEBAQEBAQEBAAAAAAAAAAAAAAAAAAAAAAAAAAABAQEBAQEBAQEBAQEAAAAAAAAAAAAAAAAAAAAAAAAAAAEBAQEBAQEBAQEBAQAAAAAAAAAAAAAAAAAAAQEBAQEBAQEBAQEBAQEBAQEBAAAAAAAAAAAAAAAAAAABAQEBAQEBAQEBAQEBAQEBAQEAAAAAAAAAAAAAAAAAAAEBAQEBAQEBAQEBAQEBAQEBAQAAAAAAAAAAAAAAAAAAAQEBAQEBAQEBAQEBAQEBAQEBAAAAAAAAAAAAAAAAAAABAQEBAQEBAQEBAQEBAQEBAQEAAAAAAAAAAAAAAAAAAAEBAQEBAQEBAQEBAQ==" + }, + "palette" : { + "originalArgb8888" : [ -265674 ], + "convertedRgb565" : [ -122 ] } }, "diagnostics" : [ ] @@ -924,14 +924,14 @@ "last_modified" : 1774359772468, "fingerprint" : "eeb7cc665386299403b7be1c272375d5077f3647c587f8033aa8c9275f840562", "metadata" : { - "palette" : { - "originalArgb8888" : [ -265674 ], - "convertedRgb565" : [ -122 ] - }, "tile" : { "width" : 32, "height" : 32, "paletteIndices" : "AQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAAAAAAAAAAABAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEAAAAAAAAAAAEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQAAAAAAAAAAAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAAAAAAAAAAABAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEAAAAAAAAAAAEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQAAAAAAAAAAAQEBAQEBAQEBAQEBAAAAAAAAAAAAAAAAAAAAAAAAAAABAQEBAQEBAQEBAQEAAAAAAAAAAAAAAAAAAAAAAAAAAAEBAQEBAQEBAQEBAQAAAAAAAAAAAAAAAAAAAAAAAAAAAQEBAQEBAQEBAQEBAAAAAAAAAAAAAAAAAAAAAAAAAAABAQEBAQEBAQEBAQEAAAAAAAAAAAAAAAAAAAAAAAAAAAEBAQEBAQEBAQEBAQAAAAAAAAAAAAAAAAAAAAAAAAAAAQEBAQEBAQEBAQEBAAAAAAAAAAAAAAAAAAAAAAAAAAABAQEBAQEBAQEBAQEAAAAAAAAAAAAAAAAAAAAAAAAAAAEBAQEBAQEBAQEBAQAAAAAAAAAAAAAAAAAAAQEBAQEBAQEBAQEBAQEBAQEBAAAAAAAAAAAAAAAAAAABAQEBAQEBAQEBAQEBAQEBAQEAAAAAAAAAAAAAAAAAAAEBAQEBAQEBAQEBAQEBAQEBAQAAAAAAAAAAAAAAAAAAAQEBAQEBAQEBAQEBAAAAAAAAAAAAAAAAAAAAAAAAAAABAQEBAQEBAQEBAQEAAAAAAAAAAAAAAAAAAAAAAAAAAAEBAQEBAQEBAQEBAQAAAAAAAAAAAAAAAAAAAQEBAQEBAQEBAQEBAQEBAQEBAAAAAAAAAAAAAAAAAAABAQEBAQEBAQEBAQEBAQEBAQEAAAAAAAAAAAAAAAAAAAEBAQEBAQEBAQEBAQEBAQEBAQAAAAAAAAAAAAAAAAAAAQEBAQEBAQEBAQEBAQEBAQEBAAAAAAAAAAAAAAAAAAABAQEBAQEBAQEBAQEBAQEBAQEAAAAAAAAAAAAAAAAAAAEBAQEBAQEBAQEBAQ==" + }, + "palette" : { + "originalArgb8888" : [ -265674 ], + "convertedRgb565" : [ -122 ] } }, "diagnostics" : [ ] @@ -942,14 +942,14 @@ "last_modified" : 1774359772470, "fingerprint" : "eeb7cc665386299403b7be1c272375d5077f3647c587f8033aa8c9275f840562", "metadata" : { - "palette" : { - "originalArgb8888" : [ -265674 ], - "convertedRgb565" : [ -122 ] - }, "tile" : { "width" : 32, "height" : 32, "paletteIndices" : "AQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAAAAAAAAAAABAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEAAAAAAAAAAAEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQAAAAAAAAAAAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAAAAAAAAAAABAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEAAAAAAAAAAAEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQAAAAAAAAAAAQEBAQEBAQEBAQEBAAAAAAAAAAAAAAAAAAAAAAAAAAABAQEBAQEBAQEBAQEAAAAAAAAAAAAAAAAAAAAAAAAAAAEBAQEBAQEBAQEBAQAAAAAAAAAAAAAAAAAAAAAAAAAAAQEBAQEBAQEBAQEBAAAAAAAAAAAAAAAAAAAAAAAAAAABAQEBAQEBAQEBAQEAAAAAAAAAAAAAAAAAAAAAAAAAAAEBAQEBAQEBAQEBAQAAAAAAAAAAAAAAAAAAAAAAAAAAAQEBAQEBAQEBAQEBAAAAAAAAAAAAAAAAAAAAAAAAAAABAQEBAQEBAQEBAQEAAAAAAAAAAAAAAAAAAAAAAAAAAAEBAQEBAQEBAQEBAQAAAAAAAAAAAAAAAAAAAQEBAQEBAQEBAQEBAQEBAQEBAAAAAAAAAAAAAAAAAAABAQEBAQEBAQEBAQEBAQEBAQEAAAAAAAAAAAAAAAAAAAEBAQEBAQEBAQEBAQEBAQEBAQAAAAAAAAAAAAAAAAAAAQEBAQEBAQEBAQEBAAAAAAAAAAAAAAAAAAAAAAAAAAABAQEBAQEBAQEBAQEAAAAAAAAAAAAAAAAAAAAAAAAAAAEBAQEBAQEBAQEBAQAAAAAAAAAAAAAAAAAAAQEBAQEBAQEBAQEBAQEBAQEBAAAAAAAAAAAAAAAAAAABAQEBAQEBAQEBAQEBAQEBAQEAAAAAAAAAAAAAAAAAAAEBAQEBAQEBAQEBAQEBAQEBAQAAAAAAAAAAAAAAAAAAAQEBAQEBAQEBAQEBAQEBAQEBAAAAAAAAAAAAAAAAAAABAQEBAQEBAQEBAQEBAQEBAQEAAAAAAAAAAAAAAAAAAAEBAQEBAQEBAQEBAQ==" + }, + "palette" : { + "originalArgb8888" : [ -265674 ], + "convertedRgb565" : [ -122 ] } }, "diagnostics" : [ ] @@ -960,14 +960,14 @@ "last_modified" : 1774359772474, "fingerprint" : "eeb7cc665386299403b7be1c272375d5077f3647c587f8033aa8c9275f840562", "metadata" : { - "palette" : { - "originalArgb8888" : [ -265674 ], - "convertedRgb565" : [ -122 ] - }, "tile" : { "width" : 32, "height" : 32, "paletteIndices" : "AQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAAAAAAAAAAABAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEAAAAAAAAAAAEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQAAAAAAAAAAAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAAAAAAAAAAABAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEAAAAAAAAAAAEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQAAAAAAAAAAAQEBAQEBAQEBAQEBAAAAAAAAAAAAAAAAAAAAAAAAAAABAQEBAQEBAQEBAQEAAAAAAAAAAAAAAAAAAAAAAAAAAAEBAQEBAQEBAQEBAQAAAAAAAAAAAAAAAAAAAAAAAAAAAQEBAQEBAQEBAQEBAAAAAAAAAAAAAAAAAAAAAAAAAAABAQEBAQEBAQEBAQEAAAAAAAAAAAAAAAAAAAAAAAAAAAEBAQEBAQEBAQEBAQAAAAAAAAAAAAAAAAAAAAAAAAAAAQEBAQEBAQEBAQEBAAAAAAAAAAAAAAAAAAAAAAAAAAABAQEBAQEBAQEBAQEAAAAAAAAAAAAAAAAAAAAAAAAAAAEBAQEBAQEBAQEBAQAAAAAAAAAAAAAAAAAAAQEBAQEBAQEBAQEBAQEBAQEBAAAAAAAAAAAAAAAAAAABAQEBAQEBAQEBAQEBAQEBAQEAAAAAAAAAAAAAAAAAAAEBAQEBAQEBAQEBAQEBAQEBAQAAAAAAAAAAAAAAAAAAAQEBAQEBAQEBAQEBAAAAAAAAAAAAAAAAAAAAAAAAAAABAQEBAQEBAQEBAQEAAAAAAAAAAAAAAAAAAAAAAAAAAAEBAQEBAQEBAQEBAQAAAAAAAAAAAAAAAAAAAQEBAQEBAQEBAQEBAQEBAQEBAAAAAAAAAAAAAAAAAAABAQEBAQEBAQEBAQEBAQEBAQEAAAAAAAAAAAAAAAAAAAEBAQEBAQEBAQEBAQEBAQEBAQAAAAAAAAAAAAAAAAAAAQEBAQEBAQEBAQEBAQEBAQEBAAAAAAAAAAAAAAAAAAABAQEBAQEBAQEBAQEBAQEBAQEAAAAAAAAAAAAAAAAAAAEBAQEBAQEBAQEBAQ==" + }, + "palette" : { + "originalArgb8888" : [ -265674 ], + "convertedRgb565" : [ -122 ] } }, "diagnostics" : [ ] @@ -978,14 +978,14 @@ "last_modified" : 1774359772476, "fingerprint" : "eeb7cc665386299403b7be1c272375d5077f3647c587f8033aa8c9275f840562", "metadata" : { - "palette" : { - "originalArgb8888" : [ -265674 ], - "convertedRgb565" : [ -122 ] - }, "tile" : { "width" : 32, "height" : 32, "paletteIndices" : "AQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAAAAAAAAAAABAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEAAAAAAAAAAAEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQAAAAAAAAAAAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAAAAAAAAAAABAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEAAAAAAAAAAAEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQAAAAAAAAAAAQEBAQEBAQEBAQEBAAAAAAAAAAAAAAAAAAAAAAAAAAABAQEBAQEBAQEBAQEAAAAAAAAAAAAAAAAAAAAAAAAAAAEBAQEBAQEBAQEBAQAAAAAAAAAAAAAAAAAAAAAAAAAAAQEBAQEBAQEBAQEBAAAAAAAAAAAAAAAAAAAAAAAAAAABAQEBAQEBAQEBAQEAAAAAAAAAAAAAAAAAAAAAAAAAAAEBAQEBAQEBAQEBAQAAAAAAAAAAAAAAAAAAAAAAAAAAAQEBAQEBAQEBAQEBAAAAAAAAAAAAAAAAAAAAAAAAAAABAQEBAQEBAQEBAQEAAAAAAAAAAAAAAAAAAAAAAAAAAAEBAQEBAQEBAQEBAQAAAAAAAAAAAAAAAAAAAQEBAQEBAQEBAQEBAQEBAQEBAAAAAAAAAAAAAAAAAAABAQEBAQEBAQEBAQEBAQEBAQEAAAAAAAAAAAAAAAAAAAEBAQEBAQEBAQEBAQEBAQEBAQAAAAAAAAAAAAAAAAAAAQEBAQEBAQEBAQEBAAAAAAAAAAAAAAAAAAAAAAAAAAABAQEBAQEBAQEBAQEAAAAAAAAAAAAAAAAAAAAAAAAAAAEBAQEBAQEBAQEBAQAAAAAAAAAAAAAAAAAAAQEBAQEBAQEBAQEBAQEBAQEBAAAAAAAAAAAAAAAAAAABAQEBAQEBAQEBAQEBAQEBAQEAAAAAAAAAAAAAAAAAAAEBAQEBAQEBAQEBAQEBAQEBAQAAAAAAAAAAAAAAAAAAAQEBAQEBAQEBAQEBAQEBAQEBAAAAAAAAAAAAAAAAAAABAQEBAQEBAQEBAQEBAQEBAQEAAAAAAAAAAAAAAAAAAAEBAQEBAQEBAQEBAQ==" + }, + "palette" : { + "originalArgb8888" : [ -265674 ], + "convertedRgb565" : [ -122 ] } }, "diagnostics" : [ ] @@ -996,14 +996,14 @@ "last_modified" : 1774359772478, "fingerprint" : "eeb7cc665386299403b7be1c272375d5077f3647c587f8033aa8c9275f840562", "metadata" : { - "palette" : { - "originalArgb8888" : [ -265674 ], - "convertedRgb565" : [ -122 ] - }, "tile" : { "width" : 32, "height" : 32, "paletteIndices" : "AQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAAAAAAAAAAABAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEAAAAAAAAAAAEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQAAAAAAAAAAAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAAAAAAAAAAABAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEAAAAAAAAAAAEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQAAAAAAAAAAAQEBAQEBAQEBAQEBAAAAAAAAAAAAAAAAAAAAAAAAAAABAQEBAQEBAQEBAQEAAAAAAAAAAAAAAAAAAAAAAAAAAAEBAQEBAQEBAQEBAQAAAAAAAAAAAAAAAAAAAAAAAAAAAQEBAQEBAQEBAQEBAAAAAAAAAAAAAAAAAAAAAAAAAAABAQEBAQEBAQEBAQEAAAAAAAAAAAAAAAAAAAAAAAAAAAEBAQEBAQEBAQEBAQAAAAAAAAAAAAAAAAAAAAAAAAAAAQEBAQEBAQEBAQEBAAAAAAAAAAAAAAAAAAAAAAAAAAABAQEBAQEBAQEBAQEAAAAAAAAAAAAAAAAAAAAAAAAAAAEBAQEBAQEBAQEBAQAAAAAAAAAAAAAAAAAAAQEBAQEBAQEBAQEBAQEBAQEBAAAAAAAAAAAAAAAAAAABAQEBAQEBAQEBAQEBAQEBAQEAAAAAAAAAAAAAAAAAAAEBAQEBAQEBAQEBAQEBAQEBAQAAAAAAAAAAAAAAAAAAAQEBAQEBAQEBAQEBAAAAAAAAAAAAAAAAAAAAAAAAAAABAQEBAQEBAQEBAQEAAAAAAAAAAAAAAAAAAAAAAAAAAAEBAQEBAQEBAQEBAQAAAAAAAAAAAAAAAAAAAQEBAQEBAQEBAQEBAQEBAQEBAAAAAAAAAAAAAAAAAAABAQEBAQEBAQEBAQEBAQEBAQEAAAAAAAAAAAAAAAAAAAEBAQEBAQEBAQEBAQEBAQEBAQAAAAAAAAAAAAAAAAAAAQEBAQEBAQEBAQEBAQEBAQEBAAAAAAAAAAAAAAAAAAABAQEBAQEBAQEBAQEBAQEBAQEAAAAAAAAAAAAAAAAAAAEBAQEBAQEBAQEBAQ==" + }, + "palette" : { + "originalArgb8888" : [ -265674 ], + "convertedRgb565" : [ -122 ] } }, "diagnostics" : [ ] @@ -1014,14 +1014,14 @@ "last_modified" : 1774359772479, "fingerprint" : "eeb7cc665386299403b7be1c272375d5077f3647c587f8033aa8c9275f840562", "metadata" : { - "palette" : { - "originalArgb8888" : [ -265674 ], - "convertedRgb565" : [ -122 ] - }, "tile" : { "width" : 32, "height" : 32, "paletteIndices" : "AQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAAAAAAAAAAABAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEAAAAAAAAAAAEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQAAAAAAAAAAAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAAAAAAAAAAABAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEAAAAAAAAAAAEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQAAAAAAAAAAAQEBAQEBAQEBAQEBAAAAAAAAAAAAAAAAAAAAAAAAAAABAQEBAQEBAQEBAQEAAAAAAAAAAAAAAAAAAAAAAAAAAAEBAQEBAQEBAQEBAQAAAAAAAAAAAAAAAAAAAAAAAAAAAQEBAQEBAQEBAQEBAAAAAAAAAAAAAAAAAAAAAAAAAAABAQEBAQEBAQEBAQEAAAAAAAAAAAAAAAAAAAAAAAAAAAEBAQEBAQEBAQEBAQAAAAAAAAAAAAAAAAAAAAAAAAAAAQEBAQEBAQEBAQEBAAAAAAAAAAAAAAAAAAAAAAAAAAABAQEBAQEBAQEBAQEAAAAAAAAAAAAAAAAAAAAAAAAAAAEBAQEBAQEBAQEBAQAAAAAAAAAAAAAAAAAAAQEBAQEBAQEBAQEBAQEBAQEBAAAAAAAAAAAAAAAAAAABAQEBAQEBAQEBAQEBAQEBAQEAAAAAAAAAAAAAAAAAAAEBAQEBAQEBAQEBAQEBAQEBAQAAAAAAAAAAAAAAAAAAAQEBAQEBAQEBAQEBAAAAAAAAAAAAAAAAAAAAAAAAAAABAQEBAQEBAQEBAQEAAAAAAAAAAAAAAAAAAAAAAAAAAAEBAQEBAQEBAQEBAQAAAAAAAAAAAAAAAAAAAQEBAQEBAQEBAQEBAQEBAQEBAAAAAAAAAAAAAAAAAAABAQEBAQEBAQEBAQEBAQEBAQEAAAAAAAAAAAAAAAAAAAEBAQEBAQEBAQEBAQEBAQEBAQAAAAAAAAAAAAAAAAAAAQEBAQEBAQEBAQEBAQEBAQEBAAAAAAAAAAAAAAAAAAABAQEBAQEBAQEBAQEBAQEBAQEAAAAAAAAAAAAAAAAAAAEBAQEBAQEBAQEBAQ==" + }, + "palette" : { + "originalArgb8888" : [ -265674 ], + "convertedRgb565" : [ -122 ] } }, "diagnostics" : [ ] @@ -1032,14 +1032,14 @@ "last_modified" : 1774359772481, "fingerprint" : "eeb7cc665386299403b7be1c272375d5077f3647c587f8033aa8c9275f840562", "metadata" : { - "palette" : { - "originalArgb8888" : [ -265674 ], - "convertedRgb565" : [ -122 ] - }, "tile" : { "width" : 32, "height" : 32, "paletteIndices" : "AQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAAAAAAAAAAABAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEAAAAAAAAAAAEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQAAAAAAAAAAAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAAAAAAAAAAABAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEAAAAAAAAAAAEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQAAAAAAAAAAAQEBAQEBAQEBAQEBAAAAAAAAAAAAAAAAAAAAAAAAAAABAQEBAQEBAQEBAQEAAAAAAAAAAAAAAAAAAAAAAAAAAAEBAQEBAQEBAQEBAQAAAAAAAAAAAAAAAAAAAAAAAAAAAQEBAQEBAQEBAQEBAAAAAAAAAAAAAAAAAAAAAAAAAAABAQEBAQEBAQEBAQEAAAAAAAAAAAAAAAAAAAAAAAAAAAEBAQEBAQEBAQEBAQAAAAAAAAAAAAAAAAAAAAAAAAAAAQEBAQEBAQEBAQEBAAAAAAAAAAAAAAAAAAAAAAAAAAABAQEBAQEBAQEBAQEAAAAAAAAAAAAAAAAAAAAAAAAAAAEBAQEBAQEBAQEBAQAAAAAAAAAAAAAAAAAAAQEBAQEBAQEBAQEBAQEBAQEBAAAAAAAAAAAAAAAAAAABAQEBAQEBAQEBAQEBAQEBAQEAAAAAAAAAAAAAAAAAAAEBAQEBAQEBAQEBAQEBAQEBAQAAAAAAAAAAAAAAAAAAAQEBAQEBAQEBAQEBAAAAAAAAAAAAAAAAAAAAAAAAAAABAQEBAQEBAQEBAQEAAAAAAAAAAAAAAAAAAAAAAAAAAAEBAQEBAQEBAQEBAQAAAAAAAAAAAAAAAAAAAQEBAQEBAQEBAQEBAQEBAQEBAAAAAAAAAAAAAAAAAAABAQEBAQEBAQEBAQEBAQEBAQEAAAAAAAAAAAAAAAAAAAEBAQEBAQEBAQEBAQEBAQEBAQAAAAAAAAAAAAAAAAAAAQEBAQEBAQEBAQEBAQEBAQEBAAAAAAAAAAAAAAAAAAABAQEBAQEBAQEBAQEBAQEBAQEAAAAAAAAAAAAAAAAAAAEBAQEBAQEBAQEBAQ==" + }, + "palette" : { + "originalArgb8888" : [ -265674 ], + "convertedRgb565" : [ -122 ] } }, "diagnostics" : [ ] @@ -1050,14 +1050,14 @@ "last_modified" : 1774359772482, "fingerprint" : "eeb7cc665386299403b7be1c272375d5077f3647c587f8033aa8c9275f840562", "metadata" : { - "palette" : { - "originalArgb8888" : [ -265674 ], - "convertedRgb565" : [ -122 ] - }, "tile" : { "width" : 32, "height" : 32, "paletteIndices" : "AQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAAAAAAAAAAABAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEAAAAAAAAAAAEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQAAAAAAAAAAAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAAAAAAAAAAABAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEAAAAAAAAAAAEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQAAAAAAAAAAAQEBAQEBAQEBAQEBAAAAAAAAAAAAAAAAAAAAAAAAAAABAQEBAQEBAQEBAQEAAAAAAAAAAAAAAAAAAAAAAAAAAAEBAQEBAQEBAQEBAQAAAAAAAAAAAAAAAAAAAAAAAAAAAQEBAQEBAQEBAQEBAAAAAAAAAAAAAAAAAAAAAAAAAAABAQEBAQEBAQEBAQEAAAAAAAAAAAAAAAAAAAAAAAAAAAEBAQEBAQEBAQEBAQAAAAAAAAAAAAAAAAAAAAAAAAAAAQEBAQEBAQEBAQEBAAAAAAAAAAAAAAAAAAAAAAAAAAABAQEBAQEBAQEBAQEAAAAAAAAAAAAAAAAAAAAAAAAAAAEBAQEBAQEBAQEBAQAAAAAAAAAAAAAAAAAAAQEBAQEBAQEBAQEBAQEBAQEBAAAAAAAAAAAAAAAAAAABAQEBAQEBAQEBAQEBAQEBAQEAAAAAAAAAAAAAAAAAAAEBAQEBAQEBAQEBAQEBAQEBAQAAAAAAAAAAAAAAAAAAAQEBAQEBAQEBAQEBAAAAAAAAAAAAAAAAAAAAAAAAAAABAQEBAQEBAQEBAQEAAAAAAAAAAAAAAAAAAAAAAAAAAAEBAQEBAQEBAQEBAQAAAAAAAAAAAAAAAAAAAQEBAQEBAQEBAQEBAQEBAQEBAAAAAAAAAAAAAAAAAAABAQEBAQEBAQEBAQEBAQEBAQEAAAAAAAAAAAAAAAAAAAEBAQEBAQEBAQEBAQEBAQEBAQAAAAAAAAAAAAAAAAAAAQEBAQEBAQEBAQEBAQEBAQEBAAAAAAAAAAAAAAAAAAABAQEBAQEBAQEBAQEBAQEBAQEAAAAAAAAAAAAAAAAAAAEBAQEBAQEBAQEBAQ==" + }, + "palette" : { + "originalArgb8888" : [ -265674 ], + "convertedRgb565" : [ -122 ] } }, "diagnostics" : [ ] @@ -1068,14 +1068,14 @@ "last_modified" : 1774359772483, "fingerprint" : "eeb7cc665386299403b7be1c272375d5077f3647c587f8033aa8c9275f840562", "metadata" : { - "palette" : { - "originalArgb8888" : [ -265674 ], - "convertedRgb565" : [ -122 ] - }, "tile" : { "width" : 32, "height" : 32, "paletteIndices" : "AQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAAAAAAAAAAABAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEAAAAAAAAAAAEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQAAAAAAAAAAAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAAAAAAAAAAABAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEAAAAAAAAAAAEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQAAAAAAAAAAAQEBAQEBAQEBAQEBAAAAAAAAAAAAAAAAAAAAAAAAAAABAQEBAQEBAQEBAQEAAAAAAAAAAAAAAAAAAAAAAAAAAAEBAQEBAQEBAQEBAQAAAAAAAAAAAAAAAAAAAAAAAAAAAQEBAQEBAQEBAQEBAAAAAAAAAAAAAAAAAAAAAAAAAAABAQEBAQEBAQEBAQEAAAAAAAAAAAAAAAAAAAAAAAAAAAEBAQEBAQEBAQEBAQAAAAAAAAAAAAAAAAAAAAAAAAAAAQEBAQEBAQEBAQEBAAAAAAAAAAAAAAAAAAAAAAAAAAABAQEBAQEBAQEBAQEAAAAAAAAAAAAAAAAAAAAAAAAAAAEBAQEBAQEBAQEBAQAAAAAAAAAAAAAAAAAAAQEBAQEBAQEBAQEBAQEBAQEBAAAAAAAAAAAAAAAAAAABAQEBAQEBAQEBAQEBAQEBAQEAAAAAAAAAAAAAAAAAAAEBAQEBAQEBAQEBAQEBAQEBAQAAAAAAAAAAAAAAAAAAAQEBAQEBAQEBAQEBAAAAAAAAAAAAAAAAAAAAAAAAAAABAQEBAQEBAQEBAQEAAAAAAAAAAAAAAAAAAAAAAAAAAAEBAQEBAQEBAQEBAQAAAAAAAAAAAAAAAAAAAQEBAQEBAQEBAQEBAQEBAQEBAAAAAAAAAAAAAAAAAAABAQEBAQEBAQEBAQEBAQEBAQEAAAAAAAAAAAAAAAAAAAEBAQEBAQEBAQEBAQEBAQEBAQAAAAAAAAAAAAAAAAAAAQEBAQEBAQEBAQEBAQEBAQEBAAAAAAAAAAAAAAAAAAABAQEBAQEBAQEBAQEBAQEBAQEAAAAAAAAAAAAAAAAAAAEBAQEBAQEBAQEBAQ==" + }, + "palette" : { + "originalArgb8888" : [ -265674 ], + "convertedRgb565" : [ -122 ] } }, "diagnostics" : [ ] @@ -1086,14 +1086,14 @@ "last_modified" : 1774359772484, "fingerprint" : "eeb7cc665386299403b7be1c272375d5077f3647c587f8033aa8c9275f840562", "metadata" : { - "palette" : { - "originalArgb8888" : [ -265674 ], - "convertedRgb565" : [ -122 ] - }, "tile" : { "width" : 32, "height" : 32, "paletteIndices" : "AQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAAAAAAAAAAABAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEAAAAAAAAAAAEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQAAAAAAAAAAAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAAAAAAAAAAABAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEAAAAAAAAAAAEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQAAAAAAAAAAAQEBAQEBAQEBAQEBAAAAAAAAAAAAAAAAAAAAAAAAAAABAQEBAQEBAQEBAQEAAAAAAAAAAAAAAAAAAAAAAAAAAAEBAQEBAQEBAQEBAQAAAAAAAAAAAAAAAAAAAAAAAAAAAQEBAQEBAQEBAQEBAAAAAAAAAAAAAAAAAAAAAAAAAAABAQEBAQEBAQEBAQEAAAAAAAAAAAAAAAAAAAAAAAAAAAEBAQEBAQEBAQEBAQAAAAAAAAAAAAAAAAAAAAAAAAAAAQEBAQEBAQEBAQEBAAAAAAAAAAAAAAAAAAAAAAAAAAABAQEBAQEBAQEBAQEAAAAAAAAAAAAAAAAAAAAAAAAAAAEBAQEBAQEBAQEBAQAAAAAAAAAAAAAAAAAAAQEBAQEBAQEBAQEBAQEBAQEBAAAAAAAAAAAAAAAAAAABAQEBAQEBAQEBAQEBAQEBAQEAAAAAAAAAAAAAAAAAAAEBAQEBAQEBAQEBAQEBAQEBAQAAAAAAAAAAAAAAAAAAAQEBAQEBAQEBAQEBAAAAAAAAAAAAAAAAAAAAAAAAAAABAQEBAQEBAQEBAQEAAAAAAAAAAAAAAAAAAAAAAAAAAAEBAQEBAQEBAQEBAQAAAAAAAAAAAAAAAAAAAQEBAQEBAQEBAQEBAQEBAQEBAAAAAAAAAAAAAAAAAAABAQEBAQEBAQEBAQEBAQEBAQEAAAAAAAAAAAAAAAAAAAEBAQEBAQEBAQEBAQEBAQEBAQAAAAAAAAAAAAAAAAAAAQEBAQEBAQEBAQEBAQEBAQEBAAAAAAAAAAAAAAAAAAABAQEBAQEBAQEBAQEBAQEBAQEAAAAAAAAAAAAAAAAAAAEBAQEBAQEBAQEBAQ==" + }, + "palette" : { + "originalArgb8888" : [ -265674 ], + "convertedRgb565" : [ -122 ] } }, "diagnostics" : [ ] @@ -1104,14 +1104,14 @@ "last_modified" : 1774359772485, "fingerprint" : "eeb7cc665386299403b7be1c272375d5077f3647c587f8033aa8c9275f840562", "metadata" : { - "palette" : { - "originalArgb8888" : [ -265674 ], - "convertedRgb565" : [ -122 ] - }, "tile" : { "width" : 32, "height" : 32, "paletteIndices" : "AQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAAAAAAAAAAABAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEAAAAAAAAAAAEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQAAAAAAAAAAAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAAAAAAAAAAABAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEAAAAAAAAAAAEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQAAAAAAAAAAAQEBAQEBAQEBAQEBAAAAAAAAAAAAAAAAAAAAAAAAAAABAQEBAQEBAQEBAQEAAAAAAAAAAAAAAAAAAAAAAAAAAAEBAQEBAQEBAQEBAQAAAAAAAAAAAAAAAAAAAAAAAAAAAQEBAQEBAQEBAQEBAAAAAAAAAAAAAAAAAAAAAAAAAAABAQEBAQEBAQEBAQEAAAAAAAAAAAAAAAAAAAAAAAAAAAEBAQEBAQEBAQEBAQAAAAAAAAAAAAAAAAAAAAAAAAAAAQEBAQEBAQEBAQEBAAAAAAAAAAAAAAAAAAAAAAAAAAABAQEBAQEBAQEBAQEAAAAAAAAAAAAAAAAAAAAAAAAAAAEBAQEBAQEBAQEBAQAAAAAAAAAAAAAAAAAAAQEBAQEBAQEBAQEBAQEBAQEBAAAAAAAAAAAAAAAAAAABAQEBAQEBAQEBAQEBAQEBAQEAAAAAAAAAAAAAAAAAAAEBAQEBAQEBAQEBAQEBAQEBAQAAAAAAAAAAAAAAAAAAAQEBAQEBAQEBAQEBAAAAAAAAAAAAAAAAAAAAAAAAAAABAQEBAQEBAQEBAQEAAAAAAAAAAAAAAAAAAAAAAAAAAAEBAQEBAQEBAQEBAQAAAAAAAAAAAAAAAAAAAQEBAQEBAQEBAQEBAQEBAQEBAAAAAAAAAAAAAAAAAAABAQEBAQEBAQEBAQEBAQEBAQEAAAAAAAAAAAAAAAAAAAEBAQEBAQEBAQEBAQEBAQEBAQAAAAAAAAAAAAAAAAAAAQEBAQEBAQEBAQEBAQEBAQEBAAAAAAAAAAAAAAAAAAABAQEBAQEBAQEBAQEBAQEBAQEAAAAAAAAAAAAAAAAAAAEBAQEBAQEBAQEBAQ==" + }, + "palette" : { + "originalArgb8888" : [ -265674 ], + "convertedRgb565" : [ -122 ] } }, "diagnostics" : [ ] @@ -1122,14 +1122,14 @@ "last_modified" : 1774359772487, "fingerprint" : "eeb7cc665386299403b7be1c272375d5077f3647c587f8033aa8c9275f840562", "metadata" : { - "palette" : { - "originalArgb8888" : [ -265674 ], - "convertedRgb565" : [ -122 ] - }, "tile" : { "width" : 32, "height" : 32, "paletteIndices" : "AQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAAAAAAAAAAABAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEAAAAAAAAAAAEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQAAAAAAAAAAAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAAAAAAAAAAABAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEAAAAAAAAAAAEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQAAAAAAAAAAAQEBAQEBAQEBAQEBAAAAAAAAAAAAAAAAAAAAAAAAAAABAQEBAQEBAQEBAQEAAAAAAAAAAAAAAAAAAAAAAAAAAAEBAQEBAQEBAQEBAQAAAAAAAAAAAAAAAAAAAAAAAAAAAQEBAQEBAQEBAQEBAAAAAAAAAAAAAAAAAAAAAAAAAAABAQEBAQEBAQEBAQEAAAAAAAAAAAAAAAAAAAAAAAAAAAEBAQEBAQEBAQEBAQAAAAAAAAAAAAAAAAAAAAAAAAAAAQEBAQEBAQEBAQEBAAAAAAAAAAAAAAAAAAAAAAAAAAABAQEBAQEBAQEBAQEAAAAAAAAAAAAAAAAAAAAAAAAAAAEBAQEBAQEBAQEBAQAAAAAAAAAAAAAAAAAAAQEBAQEBAQEBAQEBAQEBAQEBAAAAAAAAAAAAAAAAAAABAQEBAQEBAQEBAQEBAQEBAQEAAAAAAAAAAAAAAAAAAAEBAQEBAQEBAQEBAQEBAQEBAQAAAAAAAAAAAAAAAAAAAQEBAQEBAQEBAQEBAAAAAAAAAAAAAAAAAAAAAAAAAAABAQEBAQEBAQEBAQEAAAAAAAAAAAAAAAAAAAAAAAAAAAEBAQEBAQEBAQEBAQAAAAAAAAAAAAAAAAAAAQEBAQEBAQEBAQEBAQEBAQEBAAAAAAAAAAAAAAAAAAABAQEBAQEBAQEBAQEBAQEBAQEAAAAAAAAAAAAAAAAAAAEBAQEBAQEBAQEBAQEBAQEBAQAAAAAAAAAAAAAAAAAAAQEBAQEBAQEBAQEBAQEBAQEBAAAAAAAAAAAAAAAAAAABAQEBAQEBAQEBAQEBAQEBAQEAAAAAAAAAAAAAAAAAAAEBAQEBAQEBAQEBAQ==" + }, + "palette" : { + "originalArgb8888" : [ -265674 ], + "convertedRgb565" : [ -122 ] } }, "diagnostics" : [ ] @@ -1140,14 +1140,14 @@ "last_modified" : 1774359772488, "fingerprint" : "eeb7cc665386299403b7be1c272375d5077f3647c587f8033aa8c9275f840562", "metadata" : { - "palette" : { - "originalArgb8888" : [ -265674 ], - "convertedRgb565" : [ -122 ] - }, "tile" : { "width" : 32, "height" : 32, "paletteIndices" : "AQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAAAAAAAAAAABAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEAAAAAAAAAAAEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQAAAAAAAAAAAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAAAAAAAAAAABAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEAAAAAAAAAAAEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQAAAAAAAAAAAQEBAQEBAQEBAQEBAAAAAAAAAAAAAAAAAAAAAAAAAAABAQEBAQEBAQEBAQEAAAAAAAAAAAAAAAAAAAAAAAAAAAEBAQEBAQEBAQEBAQAAAAAAAAAAAAAAAAAAAAAAAAAAAQEBAQEBAQEBAQEBAAAAAAAAAAAAAAAAAAAAAAAAAAABAQEBAQEBAQEBAQEAAAAAAAAAAAAAAAAAAAAAAAAAAAEBAQEBAQEBAQEBAQAAAAAAAAAAAAAAAAAAAAAAAAAAAQEBAQEBAQEBAQEBAAAAAAAAAAAAAAAAAAAAAAAAAAABAQEBAQEBAQEBAQEAAAAAAAAAAAAAAAAAAAAAAAAAAAEBAQEBAQEBAQEBAQAAAAAAAAAAAAAAAAAAAQEBAQEBAQEBAQEBAQEBAQEBAAAAAAAAAAAAAAAAAAABAQEBAQEBAQEBAQEBAQEBAQEAAAAAAAAAAAAAAAAAAAEBAQEBAQEBAQEBAQEBAQEBAQAAAAAAAAAAAAAAAAAAAQEBAQEBAQEBAQEBAAAAAAAAAAAAAAAAAAAAAAAAAAABAQEBAQEBAQEBAQEAAAAAAAAAAAAAAAAAAAAAAAAAAAEBAQEBAQEBAQEBAQAAAAAAAAAAAAAAAAAAAQEBAQEBAQEBAQEBAQEBAQEBAAAAAAAAAAAAAAAAAAABAQEBAQEBAQEBAQEBAQEBAQEAAAAAAAAAAAAAAAAAAAEBAQEBAQEBAQEBAQEBAQEBAQAAAAAAAAAAAAAAAAAAAQEBAQEBAQEBAQEBAQEBAQEBAAAAAAAAAAAAAAAAAAABAQEBAQEBAQEBAQEBAQEBAQEAAAAAAAAAAAAAAAAAAAEBAQEBAQEBAQEBAQ==" + }, + "palette" : { + "originalArgb8888" : [ -265674 ], + "convertedRgb565" : [ -122 ] } }, "diagnostics" : [ ] @@ -1158,14 +1158,14 @@ "last_modified" : 1774359772489, "fingerprint" : "eeb7cc665386299403b7be1c272375d5077f3647c587f8033aa8c9275f840562", "metadata" : { - "palette" : { - "originalArgb8888" : [ -265674 ], - "convertedRgb565" : [ -122 ] - }, "tile" : { "width" : 32, "height" : 32, "paletteIndices" : "AQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAAAAAAAAAAABAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEAAAAAAAAAAAEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQAAAAAAAAAAAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAAAAAAAAAAABAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEAAAAAAAAAAAEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQAAAAAAAAAAAQEBAQEBAQEBAQEBAAAAAAAAAAAAAAAAAAAAAAAAAAABAQEBAQEBAQEBAQEAAAAAAAAAAAAAAAAAAAAAAAAAAAEBAQEBAQEBAQEBAQAAAAAAAAAAAAAAAAAAAAAAAAAAAQEBAQEBAQEBAQEBAAAAAAAAAAAAAAAAAAAAAAAAAAABAQEBAQEBAQEBAQEAAAAAAAAAAAAAAAAAAAAAAAAAAAEBAQEBAQEBAQEBAQAAAAAAAAAAAAAAAAAAAAAAAAAAAQEBAQEBAQEBAQEBAAAAAAAAAAAAAAAAAAAAAAAAAAABAQEBAQEBAQEBAQEAAAAAAAAAAAAAAAAAAAAAAAAAAAEBAQEBAQEBAQEBAQAAAAAAAAAAAAAAAAAAAQEBAQEBAQEBAQEBAQEBAQEBAAAAAAAAAAAAAAAAAAABAQEBAQEBAQEBAQEBAQEBAQEAAAAAAAAAAAAAAAAAAAEBAQEBAQEBAQEBAQEBAQEBAQAAAAAAAAAAAAAAAAAAAQEBAQEBAQEBAQEBAAAAAAAAAAAAAAAAAAAAAAAAAAABAQEBAQEBAQEBAQEAAAAAAAAAAAAAAAAAAAAAAAAAAAEBAQEBAQEBAQEBAQAAAAAAAAAAAAAAAAAAAQEBAQEBAQEBAQEBAQEBAQEBAAAAAAAAAAAAAAAAAAABAQEBAQEBAQEBAQEBAQEBAQEAAAAAAAAAAAAAAAAAAAEBAQEBAQEBAQEBAQEBAQEBAQAAAAAAAAAAAAAAAAAAAQEBAQEBAQEBAQEBAQEBAQEBAAAAAAAAAAAAAAAAAAABAQEBAQEBAQEBAQEBAQEBAQEAAAAAAAAAAAAAAAAAAAEBAQEBAQEBAQEBAQ==" + }, + "palette" : { + "originalArgb8888" : [ -265674 ], + "convertedRgb565" : [ -122 ] } }, "diagnostics" : [ ] @@ -1176,14 +1176,14 @@ "last_modified" : 1774359772491, "fingerprint" : "eeb7cc665386299403b7be1c272375d5077f3647c587f8033aa8c9275f840562", "metadata" : { - "palette" : { - "originalArgb8888" : [ -265674 ], - "convertedRgb565" : [ -122 ] - }, "tile" : { "width" : 32, "height" : 32, "paletteIndices" : "AQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAAAAAAAAAAABAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEAAAAAAAAAAAEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQAAAAAAAAAAAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAAAAAAAAAAABAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEAAAAAAAAAAAEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQAAAAAAAAAAAQEBAQEBAQEBAQEBAAAAAAAAAAAAAAAAAAAAAAAAAAABAQEBAQEBAQEBAQEAAAAAAAAAAAAAAAAAAAAAAAAAAAEBAQEBAQEBAQEBAQAAAAAAAAAAAAAAAAAAAAAAAAAAAQEBAQEBAQEBAQEBAAAAAAAAAAAAAAAAAAAAAAAAAAABAQEBAQEBAQEBAQEAAAAAAAAAAAAAAAAAAAAAAAAAAAEBAQEBAQEBAQEBAQAAAAAAAAAAAAAAAAAAAAAAAAAAAQEBAQEBAQEBAQEBAAAAAAAAAAAAAAAAAAAAAAAAAAABAQEBAQEBAQEBAQEAAAAAAAAAAAAAAAAAAAAAAAAAAAEBAQEBAQEBAQEBAQAAAAAAAAAAAAAAAAAAAQEBAQEBAQEBAQEBAQEBAQEBAAAAAAAAAAAAAAAAAAABAQEBAQEBAQEBAQEBAQEBAQEAAAAAAAAAAAAAAAAAAAEBAQEBAQEBAQEBAQEBAQEBAQAAAAAAAAAAAAAAAAAAAQEBAQEBAQEBAQEBAAAAAAAAAAAAAAAAAAAAAAAAAAABAQEBAQEBAQEBAQEAAAAAAAAAAAAAAAAAAAAAAAAAAAEBAQEBAQEBAQEBAQAAAAAAAAAAAAAAAAAAAQEBAQEBAQEBAQEBAQEBAQEBAAAAAAAAAAAAAAAAAAABAQEBAQEBAQEBAQEBAQEBAQEAAAAAAAAAAAAAAAAAAAEBAQEBAQEBAQEBAQEBAQEBAQAAAAAAAAAAAAAAAAAAAQEBAQEBAQEBAQEBAQEBAQEBAAAAAAAAAAAAAAAAAAABAQEBAQEBAQEBAQEBAQEBAQEAAAAAAAAAAAAAAAAAAAEBAQEBAQEBAQEBAQ==" + }, + "palette" : { + "originalArgb8888" : [ -265674 ], + "convertedRgb565" : [ -122 ] } }, "diagnostics" : [ ] @@ -1194,14 +1194,14 @@ "last_modified" : 1774359772492, "fingerprint" : "eeb7cc665386299403b7be1c272375d5077f3647c587f8033aa8c9275f840562", "metadata" : { - "palette" : { - "originalArgb8888" : [ -265674 ], - "convertedRgb565" : [ -122 ] - }, "tile" : { "width" : 32, "height" : 32, "paletteIndices" : "AQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAAAAAAAAAAABAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEAAAAAAAAAAAEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQAAAAAAAAAAAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAAAAAAAAAAABAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEAAAAAAAAAAAEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQAAAAAAAAAAAQEBAQEBAQEBAQEBAAAAAAAAAAAAAAAAAAAAAAAAAAABAQEBAQEBAQEBAQEAAAAAAAAAAAAAAAAAAAAAAAAAAAEBAQEBAQEBAQEBAQAAAAAAAAAAAAAAAAAAAAAAAAAAAQEBAQEBAQEBAQEBAAAAAAAAAAAAAAAAAAAAAAAAAAABAQEBAQEBAQEBAQEAAAAAAAAAAAAAAAAAAAAAAAAAAAEBAQEBAQEBAQEBAQAAAAAAAAAAAAAAAAAAAAAAAAAAAQEBAQEBAQEBAQEBAAAAAAAAAAAAAAAAAAAAAAAAAAABAQEBAQEBAQEBAQEAAAAAAAAAAAAAAAAAAAAAAAAAAAEBAQEBAQEBAQEBAQAAAAAAAAAAAAAAAAAAAQEBAQEBAQEBAQEBAQEBAQEBAAAAAAAAAAAAAAAAAAABAQEBAQEBAQEBAQEBAQEBAQEAAAAAAAAAAAAAAAAAAAEBAQEBAQEBAQEBAQEBAQEBAQAAAAAAAAAAAAAAAAAAAQEBAQEBAQEBAQEBAAAAAAAAAAAAAAAAAAAAAAAAAAABAQEBAQEBAQEBAQEAAAAAAAAAAAAAAAAAAAAAAAAAAAEBAQEBAQEBAQEBAQAAAAAAAAAAAAAAAAAAAQEBAQEBAQEBAQEBAQEBAQEBAAAAAAAAAAAAAAAAAAABAQEBAQEBAQEBAQEBAQEBAQEAAAAAAAAAAAAAAAAAAAEBAQEBAQEBAQEBAQEBAQEBAQAAAAAAAAAAAAAAAAAAAQEBAQEBAQEBAQEBAQEBAQEBAAAAAAAAAAAAAAAAAAABAQEBAQEBAQEBAQEBAQEBAQEAAAAAAAAAAAAAAAAAAAEBAQEBAQEBAQEBAQ==" + }, + "palette" : { + "originalArgb8888" : [ -265674 ], + "convertedRgb565" : [ -122 ] } }, "diagnostics" : [ ] @@ -1212,14 +1212,14 @@ "last_modified" : 1774359772493, "fingerprint" : "eeb7cc665386299403b7be1c272375d5077f3647c587f8033aa8c9275f840562", "metadata" : { - "palette" : { - "originalArgb8888" : [ -265674 ], - "convertedRgb565" : [ -122 ] - }, "tile" : { "width" : 32, "height" : 32, "paletteIndices" : "AQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAAAAAAAAAAABAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEAAAAAAAAAAAEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQAAAAAAAAAAAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAAAAAAAAAAABAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEAAAAAAAAAAAEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQAAAAAAAAAAAQEBAQEBAQEBAQEBAAAAAAAAAAAAAAAAAAAAAAAAAAABAQEBAQEBAQEBAQEAAAAAAAAAAAAAAAAAAAAAAAAAAAEBAQEBAQEBAQEBAQAAAAAAAAAAAAAAAAAAAAAAAAAAAQEBAQEBAQEBAQEBAAAAAAAAAAAAAAAAAAAAAAAAAAABAQEBAQEBAQEBAQEAAAAAAAAAAAAAAAAAAAAAAAAAAAEBAQEBAQEBAQEBAQAAAAAAAAAAAAAAAAAAAAAAAAAAAQEBAQEBAQEBAQEBAAAAAAAAAAAAAAAAAAAAAAAAAAABAQEBAQEBAQEBAQEAAAAAAAAAAAAAAAAAAAAAAAAAAAEBAQEBAQEBAQEBAQAAAAAAAAAAAAAAAAAAAQEBAQEBAQEBAQEBAQEBAQEBAAAAAAAAAAAAAAAAAAABAQEBAQEBAQEBAQEBAQEBAQEAAAAAAAAAAAAAAAAAAAEBAQEBAQEBAQEBAQEBAQEBAQAAAAAAAAAAAAAAAAAAAQEBAQEBAQEBAQEBAAAAAAAAAAAAAAAAAAAAAAAAAAABAQEBAQEBAQEBAQEAAAAAAAAAAAAAAAAAAAAAAAAAAAEBAQEBAQEBAQEBAQAAAAAAAAAAAAAAAAAAAQEBAQEBAQEBAQEBAQEBAQEBAAAAAAAAAAAAAAAAAAABAQEBAQEBAQEBAQEBAQEBAQEAAAAAAAAAAAAAAAAAAAEBAQEBAQEBAQEBAQEBAQEBAQAAAAAAAAAAAAAAAAAAAQEBAQEBAQEBAQEBAQEBAQEBAAAAAAAAAAAAAAAAAAABAQEBAQEBAQEBAQEBAQEBAQEAAAAAAAAAAAAAAAAAAAEBAQEBAQEBAQEBAQ==" + }, + "palette" : { + "originalArgb8888" : [ -265674 ], + "convertedRgb565" : [ -122 ] } }, "diagnostics" : [ ] @@ -1230,14 +1230,14 @@ "last_modified" : 1774359772494, "fingerprint" : "eeb7cc665386299403b7be1c272375d5077f3647c587f8033aa8c9275f840562", "metadata" : { - "palette" : { - "originalArgb8888" : [ -265674 ], - "convertedRgb565" : [ -122 ] - }, "tile" : { "width" : 32, "height" : 32, "paletteIndices" : "AQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAAAAAAAAAAABAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEAAAAAAAAAAAEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQAAAAAAAAAAAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAAAAAAAAAAABAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEAAAAAAAAAAAEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQAAAAAAAAAAAQEBAQEBAQEBAQEBAAAAAAAAAAAAAAAAAAAAAAAAAAABAQEBAQEBAQEBAQEAAAAAAAAAAAAAAAAAAAAAAAAAAAEBAQEBAQEBAQEBAQAAAAAAAAAAAAAAAAAAAAAAAAAAAQEBAQEBAQEBAQEBAAAAAAAAAAAAAAAAAAAAAAAAAAABAQEBAQEBAQEBAQEAAAAAAAAAAAAAAAAAAAAAAAAAAAEBAQEBAQEBAQEBAQAAAAAAAAAAAAAAAAAAAAAAAAAAAQEBAQEBAQEBAQEBAAAAAAAAAAAAAAAAAAAAAAAAAAABAQEBAQEBAQEBAQEAAAAAAAAAAAAAAAAAAAAAAAAAAAEBAQEBAQEBAQEBAQAAAAAAAAAAAAAAAAAAAQEBAQEBAQEBAQEBAQEBAQEBAAAAAAAAAAAAAAAAAAABAQEBAQEBAQEBAQEBAQEBAQEAAAAAAAAAAAAAAAAAAAEBAQEBAQEBAQEBAQEBAQEBAQAAAAAAAAAAAAAAAAAAAQEBAQEBAQEBAQEBAAAAAAAAAAAAAAAAAAAAAAAAAAABAQEBAQEBAQEBAQEAAAAAAAAAAAAAAAAAAAAAAAAAAAEBAQEBAQEBAQEBAQAAAAAAAAAAAAAAAAAAAQEBAQEBAQEBAQEBAQEBAQEBAAAAAAAAAAAAAAAAAAABAQEBAQEBAQEBAQEBAQEBAQEAAAAAAAAAAAAAAAAAAAEBAQEBAQEBAQEBAQEBAQEBAQAAAAAAAAAAAAAAAAAAAQEBAQEBAQEBAQEBAQEBAQEBAAAAAAAAAAAAAAAAAAABAQEBAQEBAQEBAQEBAQEBAQEAAAAAAAAAAAAAAAAAAAEBAQEBAQEBAQEBAQ==" + }, + "palette" : { + "originalArgb8888" : [ -265674 ], + "convertedRgb565" : [ -122 ] } }, "diagnostics" : [ ] @@ -1248,14 +1248,14 @@ "last_modified" : 1774359772495, "fingerprint" : "eeb7cc665386299403b7be1c272375d5077f3647c587f8033aa8c9275f840562", "metadata" : { - "palette" : { - "originalArgb8888" : [ -265674 ], - "convertedRgb565" : [ -122 ] - }, "tile" : { "width" : 32, "height" : 32, "paletteIndices" : "AQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAAAAAAAAAAABAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEAAAAAAAAAAAEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQAAAAAAAAAAAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAAAAAAAAAAABAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEAAAAAAAAAAAEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQAAAAAAAAAAAQEBAQEBAQEBAQEBAAAAAAAAAAAAAAAAAAAAAAAAAAABAQEBAQEBAQEBAQEAAAAAAAAAAAAAAAAAAAAAAAAAAAEBAQEBAQEBAQEBAQAAAAAAAAAAAAAAAAAAAAAAAAAAAQEBAQEBAQEBAQEBAAAAAAAAAAAAAAAAAAAAAAAAAAABAQEBAQEBAQEBAQEAAAAAAAAAAAAAAAAAAAAAAAAAAAEBAQEBAQEBAQEBAQAAAAAAAAAAAAAAAAAAAAAAAAAAAQEBAQEBAQEBAQEBAAAAAAAAAAAAAAAAAAAAAAAAAAABAQEBAQEBAQEBAQEAAAAAAAAAAAAAAAAAAAAAAAAAAAEBAQEBAQEBAQEBAQAAAAAAAAAAAAAAAAAAAQEBAQEBAQEBAQEBAQEBAQEBAAAAAAAAAAAAAAAAAAABAQEBAQEBAQEBAQEBAQEBAQEAAAAAAAAAAAAAAAAAAAEBAQEBAQEBAQEBAQEBAQEBAQAAAAAAAAAAAAAAAAAAAQEBAQEBAQEBAQEBAAAAAAAAAAAAAAAAAAAAAAAAAAABAQEBAQEBAQEBAQEAAAAAAAAAAAAAAAAAAAAAAAAAAAEBAQEBAQEBAQEBAQAAAAAAAAAAAAAAAAAAAQEBAQEBAQEBAQEBAQEBAQEBAAAAAAAAAAAAAAAAAAABAQEBAQEBAQEBAQEBAQEBAQEAAAAAAAAAAAAAAAAAAAEBAQEBAQEBAQEBAQEBAQEBAQAAAAAAAAAAAAAAAAAAAQEBAQEBAQEBAQEBAQEBAQEBAAAAAAAAAAAAAAAAAAABAQEBAQEBAQEBAQEBAQEBAQEAAAAAAAAAAAAAAAAAAAEBAQEBAQEBAQEBAQ==" + }, + "palette" : { + "originalArgb8888" : [ -265674 ], + "convertedRgb565" : [ -122 ] } }, "diagnostics" : [ ] @@ -1266,14 +1266,14 @@ "last_modified" : 1775797786950, "fingerprint" : "0526996900bdeef23c72fe987fb45800f11895946dcd5f0f7f8390c879069a37", "metadata" : { - "palette" : { - "originalArgb8888" : [ -265674, -1736296, -13905598, -11518505, -14439577, -2467509 ], - "convertedRgb565" : [ -122, -7149, 11912, 20986, 9548, -9527 ] - }, "tile" : { "width" : 32, "height" : 32, "paletteIndices" : "AQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQECAgIBAQEBAQEBAQEBAQEBAQEBAwMDAwMDAQEBAQEBAgICAgICAgIBAQEBAQEBAQEBAQMDAwMDAwMBAQEBAQICAgICAgICAQEBAQEBAQEBAQEBAQMDAwMDAQEBAQEBAgICAgICAgEBAQEBAQQEBAQBAQEBAQEBAQEBAQEBAQEBAgICAgIBAQEBAQEEBAQEBAQBAQEBAQEBAQEBAQEBAQEBAgECAQEBAQEBAQQEBAQEAQEBAQEBAAAAAAAAAAABAQECAQEBAQEBAQEEBAQEBAEBAQEBAQEAAAAAAAAAAAEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQAAAAAAAAAAAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAAAAAAAAAAABAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEAAAAAAAAAAAEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQAAAAAAAAAAAQEBAQEBAQEBAQEBAAAAAAAAAAAAAAAAAAAAAAAAAAABAQEBAQEBAQEBAQEAAAAAAAAAAAAAAAAAAAAAAAAAAAEBAQEBAQEBAQEBAQAAAAAAAAAAAAAAAAAAAAAAAAAAAQEBAQEBAQUBAQEBAAAAAAAAAAAAAAAAAAAAAAAAAAABAQEBAQUFBQEBAQEAAAAAAAAAAAAAAAAAAAAAAAAAAAEBAQEFBQUFBQEBAQAAAAAAAAAAAAAAAAAAAAAAAAAAAQEBBQUFBQUBAQEBAAAAAAAAAAAAAAAAAAAAAAAAAAABAQEBBQUFAQEBAQEAAAAAAAAAAAAAAAAAAAAAAAAAAAEBAQEBAQEBAQEBAQAAAAAAAAAAAAAAAAAAAQEBAQEBAQEBAQEBAQEBAQEBAAAAAAAAAAAAAAAAAAABAQEBAQEBAQEBAQEBAQEBAQEAAAAAAAAAAAAAAAAAAAEBAQEBAQYGBgYBAQEBAQEBAQAAAAAAAAAAAAAAAAAAAQEBAQEBBgYGBgEBAAAAAAAAAAAAAAAAAAAAAAAAAAABAQEBAQEGBgYGAQEAAAAAAAAAAAAAAAAAAAAAAAAAAAEBAQEBAQYGBgYBAQAAAAAAAAAAAAAAAAAAAQEBAQEBAQEBAQEBAQYGAQEBAAAAAAAAAAAAAAAAAAABAQEBAQEBAQEBAQEBAQEBAQEAAAAAAAAAAAAAAAAAAAEBAQEBAQEBAQEBAQEBAQEBAQAAAAAAAAAAAAAAAAAAAQEBAQEBAQEBAQEBAQEBAQEBAAAAAAAAAAAAAAAAAAABAQEBAQEBAQEBAQEBAQEBAQEAAAAAAAAAAAAAAAAAAAEBAQEBAQEBAQEBAQ==" + }, + "palette" : { + "originalArgb8888" : [ -265674, -1736296, -13905598, -11518505, -14439577, -2467509 ], + "convertedRgb565" : [ -122, -7149, 11912, 20986, 9548, -9527 ] } }, "diagnostics" : [ ] @@ -1314,14 +1314,14 @@ "last_modified" : 1775797786770, "fingerprint" : "aa7d241deabcebe29a6096e14eaf16fdc06cf06380c11a507620b00fc7bff094", "metadata" : { - "palette" : { - "originalArgb8888" : [ -265674 ], - "convertedRgb565" : [ -122 ] - }, "tile" : { "width" : 16, "height" : 16, "paletteIndices" : "AQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAAAAAAEBAQEBAQEBAQEBAQAAAAABAQEBAQEBAQEBAQEAAAAAAQEBAQEBAAAAAAAAAAAAAAEBAQEBAQAAAAAAAAAAAAABAQEBAQEAAAAAAAAAAAAAAQEBAQEBAAAAAAAAAAAAAAEBAQEBAQAAAAAAAAABAQEBAQEBAQEAAAAAAAAAAQEBAQEBAAAAAAAAAAAAAAEBAQEBAQAAAAAAAAABAQEBAQEBAQEAAAAAAAAAAQEBAQEBAQEBAAAAAAAAAAEBAQEBAQ==" + }, + "palette" : { + "originalArgb8888" : [ -265674 ], + "convertedRgb565" : [ -122 ] } }, "diagnostics" : [ ] @@ -1344,14 +1344,14 @@ "last_modified" : 1775797786709, "fingerprint" : "6ca635a7906067b6a2a8460a8562718c445783e6df18b9f2c80c83c5ac569db6", "metadata" : { - "palette" : { - "originalArgb8888" : [ -130562, -14145496, -2043712, -460560, -13082456, -6252424, -10977088 ], - "convertedRgb565" : [ -2017, 10565, -6504, -34, 15125, -23345, 23576 ] - }, "tile" : { "width" : 32, "height" : 32, "paletteIndices" : "AQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQICAgICAgICAgAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAICAwMDAwMDAgAAAAAAAAAAAAACAgIAAAAAAAAAAAAAAAIEBQUFBQUDAgAAAAAAAgICAgMDAwIAAAAAAAAAAAAAAgQFAwYGBgUDAgICAgIDAwMDBQUFAwIAAAAAAAAAAAACBAUDBgYGBgUEBAQEAwUFBQUGAwMFBAICAAAAAAAAAAIEBQMGBgYGAwUFBwcFBgYGBgMDAwMFBAQCAgAAAAAAAgQFAwYGBgMDAwQEBAMGBgYGBgMDAwMHBwQDAgAAAAACBAUDBgYGAwMDAwQEAwYGBgYGAwMDBAQEBQUDAgIAAAIEBQMGBgYDAwMDBAQDBgYGBgYDAwMDBAQDAwUGAgAAAgQFAwYGBgMDAwMEBAMGBgYGBQUFBQUEBAUFBgIAAAACBAUDBgYGAwMDAwQEAwYGBQUGAwMDAwcHAwYCAAAAAAIEBQMFBQUFBQMDBAQDBgUGBgICAgICBAQCAgAAAAAAAgQFBQYGBgYDBQMEBAMFBgICAAAAAAACAgAAAAAAAAACBAMDBgICAgIDBQcHBQYCAAAAAAAAAAAAAAAAAAAAAgIDAwMCAAAAAAIEBAMDAgAAAAAAAAAAAAAAAAAAAAICAgICAgAAAAAAAAICAgIAAAAAAAAAAAAAAAAAAAAAAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQ==" + }, + "palette" : { + "originalArgb8888" : [ -130562, -14145496, -2043712, -460560, -13082456, -6252424, -10977088 ], + "convertedRgb565" : [ -2017, 10565, -6504, -34, 15125, -23345, 23576 ] } }, "diagnostics" : [ { @@ -1396,14 +1396,14 @@ "last_modified" : 1775797786706, "fingerprint" : "7feab8c868bb446afd3dd7250e70504fb0ca228f463650d2dd7c525144e0b321", "metadata" : { - "palette" : { - "originalArgb8888" : [ -16777216, -2109505, -526353, -395279, -130562, -13082456, -10911807, -6318217, -6186631, -6187143, -6318215, -13148249, -13016663, -14080215 ], - "convertedRgb565" : [ 0, -8585, -2115, -66, -2017, 15125, 23544, -25426, -23345, -23377, -25425, 13044, 15125, 10533 ] - }, "tile" : { "width" : 32, "height" : 32, "paletteIndices" : "AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAEBAQEBAQEAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAEBAgMDBAEBAQEBBQUFAAUFBQUFBQUBAQAAAAAAAAAAAAECBgcHBAIICAkBBQUFBQUFBQEBAQICAQEAAAAFBQAAAQIGAwMHBgYGBgIBBQUFBQEBCgIIBgYDBAEBBQUFAAABAgYDAwIJCQsJBgIBAQEBCAgMDA0JAgcHAwMBBQUAAAECBgMDAgsLCwsLBgMDAwIGBgkCCwILAgIHAwEFBQAAAQIGAwMCCQkJCQkCBgcHBgsLCwsCCwICAwMHAwEFAAABAgYDAgkJCQkJCQICAwMCCQkJAgkGBgYHBwcDDgUAAAECBwMCCQkJCQkJAgIDAgkJCQkGBgsCAwMDAwQEAQAAAQIHAwIJCQkJCQkCAgMCCQkJBgkLAQEBAQEBAQQBAAABAgcDAgkJCQkJAgICAwILCQYJAQEFBQUFBQUFAQEAAAECBwMCCQkJCQYGAgIDAgkGCwEFBQUFBQUFBQAAAAAAAQIHAwIJCQYGCQIGBgcMBgkBBQUFBQUFBQAAAAAAAAABAgcGBgYGCQsBAQIDBAIKAQUFBQUFBQAAAAAAAAAAAQECAwIJCQkBAQAAAQEBAQEAAAAAAAAAAAAAAAAAAAEBAQEBAQEBAQAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA==" + }, + "palette" : { + "originalArgb8888" : [ -16777216, -2109505, -526353, -395279, -130562, -13082456, -10911807, -6318217, -6186631, -6187143, -6318215, -13148249, -13016663, -14080215 ], + "convertedRgb565" : [ 0, -8585, -2115, -66, -2017, 15125, 23544, -25426, -23345, -23377, -25425, 13044, 15125, 10533 ] } }, "diagnostics" : [ ] @@ -1414,14 +1414,14 @@ "last_modified" : 1775797786710, "fingerprint" : "c363f3ef7f32d9b249c7dc8babdb3eb5aae68c524099e5e97290202b054dda71", "metadata" : { - "palette" : { - "originalArgb8888" : [ -14671840, -11431408, -9326048, -802016, -3964416, -5086944, -789517, -810399, -1863087, -10403552, -5078447 ], - "convertedRgb565" : [ 8452, 21634, 30084, -2556, -15360, -19708, -2146, -2804, -7030, 25092, -19446 ] - }, "tile" : { "width" : 32, "height" : 32, "paletteIndices" : "AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAABAQEBAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAEBAQICAwMBAQAAAAAAAAAAAAAAAAAAAAAAAAAAAAABBAQBAgIDAwMCAQAAAAAAAAAAAAAAAAAAAAAAAAAAAQUFBAQBAgIDAgICAQAAAAAAAAAAAAAAAAAAAAAAAAABBQEFBAUBAgICAgMBAAAAAAAAAAAAAAAAAAAAAAAAAAABBgEFBQUBAgECAgMBAAAAAAAAAAAAAAAAAAAAAAAAAAEGBwEFBAEBCAECAwEAAAAAAAAAAAAAAAAAAAAAAAAAAQgBBwEEAQgJAQICAQAAAAAAAAAAAAAAAAAAAAAAAAEICAEHAQQBCQYBAgIBAAAAAAAAAAAAAAAAAAAAAAAAAAEGCQkBBQEGAQUBAgEAAAAAAAAAAAAAAAAAAAAAAAAAAAEBBgYBBgEBAQABAAAAAAAAAAAAAAAAAAAAAAAAAAAAAQcBAQEBAgIBAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAECAwECAwIBAgEAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAQECAQcHBwECAQAAAAAAAAAAAAAAAAAAAAAAAAAAAAABBAEBAQEBAQECAQAAAAAAAAAAAAAAAAAAAAAAAAAAAAABAgEJCgoBAgEAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAQEBAQEJCQEBAQAAAAAAAAAAAAAAAAAAAAAAAAAAAAEBAQEKAQEBAQEBAQAAAAAAAAAAAAAAAAAAAAAAAAAAAQEBAQELCwoKAQEBAAAAAAAAAAAAAAAAAAAAAAAAAAAAAQEBAQEBAQEBAQAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAEBAQEBAQAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA==" + }, + "palette" : { + "originalArgb8888" : [ -14671840, -11431408, -9326048, -802016, -3964416, -5086944, -789517, -810399, -1863087, -10403552, -5078447 ], + "convertedRgb565" : [ 8452, 21634, 30084, -2556, -15360, -19708, -2146, -2804, -7030, 25092, -19446 ] } }, "diagnostics" : [ ] @@ -1432,14 +1432,14 @@ "last_modified" : 1775797786711, "fingerprint" : "e2130efbb9643b41a4fb62619f2713402f9622c7db040fe18d929609ef70b89a", "metadata" : { - "palette" : { - "originalArgb8888" : [ -14671840, -11431408, -9326048, -802016, -3964416, -5086944, -789517, -810399, -1863087, -10403552, -5078447 ], - "convertedRgb565" : [ 8452, 21634, 30084, -2556, -15360, -19708, -2146, -2804, -7030, 25092, -19446 ] - }, "tile" : { "width" : 32, "height" : 32, "paletteIndices" : "AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAQEBAQAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAABAQECAgMDAQEAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAQQEAQICAwMDAgEAAAAAAAAAAAAAAAAAAAAAAAAAAAEFBQQEAQICAwICAgEAAAAAAAAAAAAAAAAAAAAAAAAAAQUBBQQFAQICAgIDAQAAAAAAAAAAAAAAAAAAAAAAAAAAAQYBBQUFAQIBAgIDAQAAAAAAAAAAAAAAAAAAAAAAAAABBgcBBQQBAQgBAgMBAAAAAAAAAAAAAAAAAAAAAAAAAAEIAQcBBAEICQECAgEAAAAAAAAAAAAAAAAAAAAAAAABCAgBBwEEAQkGAQICAQAAAAAAAAAAAAAAAAAAAAAAAAABBgkJAQUBBgEFAQIBAAAAAAAAAAAAAAAAAAAAAAAAAAABAQYGAQYBAQEAAQAAAAAAAAAAAAAAAAAAAAAAAAAAAAEHAQEBAQECAQAAAAAAAAAAAAAAAAAAAAAAAAAAAAABAgEBBwMBAwMBAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAEBCQoBBwEDAgEBAAAAAAAAAAAAAAAAAAAAAAAAAAABAgEJCQoBAgIBAQIBAAAAAAAAAAAAAAAAAAAAAAAAAAECAgEBAQICAQECAQEAAAAAAAAAAAAAAAAAAAAAAAAAAAEBAgECAQECAgEBAQAAAAAAAAAAAAAAAAAAAAAAAAAAAQEBAQICAgEBAQoKAQAAAAAAAAAAAAAAAAAAAAAAAAEBAQEBAQEBAQELCwoBAAAAAAAAAAAAAAAAAAAAAAAAAQEBAQEBAQEBAQsLAQEAAAAAAAAAAAAAAAAAAAAAAAAAAQEBAQEBAQEBAQEBAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAEBAQEBAQAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA==" + }, + "palette" : { + "originalArgb8888" : [ -14671840, -11431408, -9326048, -802016, -3964416, -5086944, -789517, -810399, -1863087, -10403552, -5078447 ], + "convertedRgb565" : [ 8452, 21634, 30084, -2556, -15360, -19708, -2146, -2804, -7030, 25092, -19446 ] } }, "diagnostics" : [ ] @@ -1450,14 +1450,14 @@ "last_modified" : 1775797786713, "fingerprint" : "9216dfc6a6226fac398e9f781550d23fbfaa65bd377cdda69187149beca114ec", "metadata" : { - "palette" : { - "originalArgb8888" : [ -14671840, -11431408, -9326048, -802016, -3964416, -5086944, -789517, -810399, -1863087, -10403552, -5078447 ], - "convertedRgb565" : [ 8452, 21634, 30084, -2556, -15360, -19708, -2146, -2804, -7030, 25092, -19446 ] - }, "tile" : { "width" : 32, "height" : 32, "paletteIndices" : "AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAQEBAQAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAEBAQECAgMDAQEAAAEBAAAAAAAAAAAAAAAAAAAAAAABBAQEAQICAwMDAgEBAwEAAAAAAAAAAAAAAAAAAAAAAAEFBQQEAQICAwICAQIDAQAAAAAAAAAAAAAAAAAAAAAAAAEBBQQFAQICAgICAwEBAAAAAAAAAAAAAAAAAAAAAAAAAQYBBQUFAQIBAgICAQAAAAAAAAAAAAAAAAAAAAAAAAABBgcBBQQFAQgBAQEBAAAAAAAAAAAAAAAAAAAAAAAAAAEIAQcBBAUBCQEBBQUBAAAAAAAAAAAAAAAAAAAAAAABCAgBBwgBBAUBAQUBAAAAAAAAAAAAAAAAAAAAAAAAAAABBgkJBgYBAQEBAQAAAAAAAAAAAAAAAAAAAAAAAAAAAAABAQYGBgYBAQAAAAAAAAAAAAAAAAAAAAAAAAAAAAABAQEBAQEBAQMBAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAEJCgEHAwECAwEBAQAAAAAAAAAAAAAAAAAAAAAAAAABAQkKAQcCAQIDAQEBAQAAAAAAAAAAAAAAAAAAAAAAAAEKAQEBAQECAgEBAgELAQAAAAAAAAAAAAAAAAAAAAAAAQEKAQICAQEBAgIBAQoLAQAAAAAAAAAAAAAAAAAAAAAAAQEBAQECAgICAQEAAQEAAAAAAAAAAAAAAAAAAAAAAAAAAQEBAQEBAQEBAQAAAAAAAAAAAAAAAAAAAAAAAAAAAAEBAQEBAQEBAQEBAQAAAAAAAAAAAAAAAAAAAAAAAAAAAQEBAQEBAQEBAQEBAAAAAAAAAAAAAAAAAAAAAAAAAAAAAQEBAQEBAQEBAQAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAEBAQEBAQAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA==" + }, + "palette" : { + "originalArgb8888" : [ -14671840, -11431408, -9326048, -802016, -3964416, -5086944, -789517, -810399, -1863087, -10403552, -5078447 ], + "convertedRgb565" : [ 8452, 21634, 30084, -2556, -15360, -19708, -2146, -2804, -7030, 25092, -19446 ] } }, "diagnostics" : [ ] @@ -1468,14 +1468,14 @@ "last_modified" : 1775797786712, "fingerprint" : "ebc4b7ca7bb1455288681c5d71424f60f658a44cb343d0c3934329cec676c867", "metadata" : { - "palette" : { - "originalArgb8888" : [ -14671840, -11431408, -9326048, -802016, -3964416, -5086944, -789517, -810399, -1863087, -10403552, -5078447 ], - "convertedRgb565" : [ 8452, 21634, 30084, -2556, -15360, -19708, -2146, -2804, -7030, 25092, -19446 ] - }, "tile" : { "width" : 32, "height" : 32, "paletteIndices" : "AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAABAQEBAAAAAAEBAAAAAAAAAAAAAAAAAAAAAAAAAAEBAQICAwMBAQEBAwEAAAAAAAAAAAAAAAAAAAAAAAABBAQBAgIDAwMCAQMDAQAAAAAAAAAAAAAAAAAAAAAAAQUFBAQBAgIDAgICAwIBAAAAAAAAAAAAAAAAAAAAAAABBQEFBAUBAgICAgMCAQAAAAAAAAAAAAAAAAAAAAAAAAABBgEFBQUBAgECAgIBAAAAAAAAAAAAAAAAAAAAAAAAAAEGBwEFBAUBCAEBAQAAAAAAAAAAAAAAAAAAAAAAAAAAAQgBBwEEBQEJAQEAAAAAAAAAAAAAAAAAAAAAAAAAAAEICAEHCQEEBQEFAQAAAAAAAAAAAAAAAAAAAAAAAAAAAQEBCQkGBgEBAQUBAAAAAAAAAAAAAAAAAAAAAAAAAAABCQoBAQEGBgEBAQUBAAAAAAAAAAAAAAAAAAAAAAAAAAEKCgEHAgEBAQMBAQAAAAAAAAAAAAAAAAAAAAAAAAAAAAEBBwICAQIDAwEBAAAAAAAAAAAAAAAAAAAAAAAAAAABAQEBAQECAgMBAQIBAAAAAAAAAAAAAAAAAAAAAAAAAQoBAQIBAgICAgECAQEAAAAAAAAAAAAAAAAAAAAAAAABCgoBAgIBAQEBAgELAQAAAAAAAAAAAAAAAAAAAAAAAAEBAQEBAQICAgIBAQEAAAAAAAAAAAAAAAAAAAAAAAAAAAEBAQEBAQEBAQEBAQAAAAAAAAAAAAAAAAAAAAAAAAAAAQEBAQEBAQEBAQEBAAAAAAAAAAAAAAAAAAAAAAAAAAAAAQEBAQEBAQEBAQAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAEBAQEBAQAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA==" + }, + "palette" : { + "originalArgb8888" : [ -14671840, -11431408, -9326048, -802016, -3964416, -5086944, -789517, -810399, -1863087, -10403552, -5078447 ], + "convertedRgb565" : [ 8452, 21634, 30084, -2556, -15360, -19708, -2146, -2804, -7030, 25092, -19446 ] } }, "diagnostics" : [ ] @@ -1486,14 +1486,14 @@ "last_modified" : 1775797786718, "fingerprint" : "c363f3ef7f32d9b249c7dc8babdb3eb5aae68c524099e5e97290202b054dda71", "metadata" : { - "palette" : { - "originalArgb8888" : [ -14671840, -11431408, -9326048, -802016, -3964416, -5086944, -789517, -810399, -1863087, -10403552, -5078447 ], - "convertedRgb565" : [ 8452, 21634, 30084, -2556, -15360, -19708, -2146, -2804, -7030, 25092, -19446 ] - }, "tile" : { "width" : 32, "height" : 32, "paletteIndices" : "AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAABAQEBAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAEBAQICAwMBAQAAAAAAAAAAAAAAAAAAAAAAAAAAAAABBAQBAgIDAwMCAQAAAAAAAAAAAAAAAAAAAAAAAAAAAQUFBAQBAgIDAgICAQAAAAAAAAAAAAAAAAAAAAAAAAABBQEFBAUBAgICAgMBAAAAAAAAAAAAAAAAAAAAAAAAAAABBgEFBQUBAgECAgMBAAAAAAAAAAAAAAAAAAAAAAAAAAEGBwEFBAEBCAECAwEAAAAAAAAAAAAAAAAAAAAAAAAAAQgBBwEEAQgJAQICAQAAAAAAAAAAAAAAAAAAAAAAAAEICAEHAQQBCQYBAgIBAAAAAAAAAAAAAAAAAAAAAAAAAAEGCQkBBQEGAQUBAgEAAAAAAAAAAAAAAAAAAAAAAAAAAAEBBgYBBgEBAQABAAAAAAAAAAAAAAAAAAAAAAAAAAAAAQcBAQEBAgIBAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAECAwECAwIBAgEAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAQECAQcHBwECAQAAAAAAAAAAAAAAAAAAAAAAAAAAAAABBAEBAQEBAQECAQAAAAAAAAAAAAAAAAAAAAAAAAAAAAABAgEJCgoBAgEAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAQEBAQEJCQEBAQAAAAAAAAAAAAAAAAAAAAAAAAAAAAEBAQEKAQEBAQEBAQAAAAAAAAAAAAAAAAAAAAAAAAAAAQEBAQELCwoKAQEBAAAAAAAAAAAAAAAAAAAAAAAAAAAAAQEBAQEBAQEBAQAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAEBAQEBAQAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA==" + }, + "palette" : { + "originalArgb8888" : [ -14671840, -11431408, -9326048, -802016, -3964416, -5086944, -789517, -810399, -1863087, -10403552, -5078447 ], + "convertedRgb565" : [ 8452, 21634, 30084, -2556, -15360, -19708, -2146, -2804, -7030, 25092, -19446 ] } }, "diagnostics" : [ ] @@ -1504,14 +1504,14 @@ "last_modified" : 1775797786717, "fingerprint" : "1ba8ce75c445396334737143e0cfa56c87a1fb64cca8ad0962192594849249eb", "metadata" : { - "palette" : { - "originalArgb8888" : [ -14671840, -11431408, -9326048, -802016, -3964416, -5086944, -789517, -810399, -1863087, -10403552 ], - "convertedRgb565" : [ 8452, 21634, 30084, -2556, -15360, -19708, -2146, -2804, -7030, 25092 ] - }, "tile" : { "width" : 32, "height" : 32, "paletteIndices" : "AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAABAQEBAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAEBAQICAwMBAQAAAAAAAAAAAAAAAAAAAAAAAAAAAAABBAQBAgIDAwMCAQAAAAAAAAAAAAAAAAAAAAAAAAAAAQUFBAQBAgIDAgICAQAAAAAAAAAAAAAAAAAAAAAAAAABBQEFBAUBAgICAgMBAAAAAAAAAAAAAAAAAAAAAAAAAAABBgEFBQUBAgECAgMBAAAAAAAAAAAAAAAAAAAAAAAAAAEGBwEFBAEBCAECAwEAAAAAAAAAAAAAAAAAAAAAAAAAAQgBBwEEAQgJAQICAQAAAAAAAAAAAAAAAAAAAAAAAAEICAEHAQQBCQYBAgIBAAAAAAAAAAAAAAAAAAAAAAAAAAEGCQkBBQEGAQUBAgEAAAAAAAAAAAAAAAAAAAAAAAAAAAEBBgYBAQEBAQABAAAAAAAAAAAAAAAAAAAAAAAAAAAAAQcBAQEDAQEAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAABAwMBAgcHAQAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAQMDAwIBAQEBAQAAAAAAAAAAAAAAAAAAAAAAAAAAAAABBAIDAgEKCgECAQAAAAAAAAAAAAAAAAAAAAAAAAAAAAECAQEBAQkJAQIBAAAAAAAAAAAAAAAAAAAAAAAAAAAAAQECAgICAQECAQoBAAAAAAAAAAAAAAAAAAAAAAAAAAABAQEBAQICAgEKCgEAAAAAAAAAAAAAAAAAAAAAAAAAAQEBAQEBAQEBCgoKAQAAAAAAAAAAAAAAAAAAAAAAAAABAQEBAQEBAQEBAQEAAAAAAAAAAAAAAAAAAAAAAAAAAAABAQEBAQEBAQEBAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAQEBAQEBAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA==" + }, + "palette" : { + "originalArgb8888" : [ -14671840, -11431408, -9326048, -802016, -3964416, -5086944, -789517, -810399, -1863087, -10403552 ], + "convertedRgb565" : [ 8452, 21634, 30084, -2556, -15360, -19708, -2146, -2804, -7030, 25092 ] } }, "diagnostics" : [ ] @@ -1522,14 +1522,14 @@ "last_modified" : 1775797786714, "fingerprint" : "5e0954447699c6d5eac7550f1a10cf520efcddad0b9fbd9a716434da9d9550d4", "metadata" : { - "palette" : { - "originalArgb8888" : [ -14671840, -11431408, -9326048, -802016, -3964416, -5086944, -789517, -810399, -1863087, -10403552, -5078447 ], - "convertedRgb565" : [ 8452, 21634, 30084, -2556, -15360, -19708, -2146, -2804, -7030, 25092, -19446 ] - }, "tile" : { "width" : 32, "height" : 32, "paletteIndices" : "AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAABAQEBAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAQEBAQICAwMBAQAAAAAAAAAAAAAAAAAAAAAAAAAAAAEEBAQBAgIDAwMCAQABAQAAAAAAAAAAAAAAAAAAAAAAAQUFBAQBAgIDAgIBAQMBAAAAAAAAAAAAAAAAAAAAAAAAAQEFBAUBAgICAgIDAwEAAAAAAAAAAAAAAAAAAAAAAAABBgEFBQUBAgECAgIBAAAAAAAAAAAAAAAAAAAAAAAAAAEGBwEFBAUBCAEBAQEAAAAAAAAAAAAAAAAAAAAAAAAAAQgBBwEEBQEJAQEFBQEAAAAAAAAAAAAAAAAAAAAAAAEICAEHCAEEBQEBBQEBAAAAAAAAAAAAAAAAAAAAAAAAAAEGCQkGBgEBAQEBAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAEBBgYGAQIDAQAAAAAAAAAAAAAAAAAAAAAAAAAAAAABCQEBAQEBAQEHAQAAAAAAAAAAAAAAAAAAAAAAAAAAAQEBBwcDAgEKCgEBAAAAAAAAAAAAAAAAAAAAAAAAAAABAgIBAwMCAQkJAQEAAAAAAAAAAAAAAAAAAAAAAAAAAQEBAQIBAgMCAQEBCgEAAAAAAAAAAAAAAAAAAAAAAAABCwsKAQIBAQECAgEKAQAAAAAAAAAAAAAAAAAAAAAAAAABCwsKAQICAgIBCgoBAAAAAAAAAAAAAAAAAAAAAAAAAAABAQEBAQEBAQEBAQAAAAAAAAAAAAAAAAAAAAAAAAAAAQEBAQEBAQEBAQEBAAAAAAAAAAAAAAAAAAAAAAAAAAABAQEBAQEBAQEBAQEAAAAAAAAAAAAAAAAAAAAAAAAAAAABAQEBAQEBAQEBAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAQEBAQEBAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA==" + }, + "palette" : { + "originalArgb8888" : [ -14671840, -11431408, -9326048, -802016, -3964416, -5086944, -789517, -810399, -1863087, -10403552, -5078447 ], + "convertedRgb565" : [ 8452, 21634, 30084, -2556, -15360, -19708, -2146, -2804, -7030, 25092, -19446 ] } }, "diagnostics" : [ ] @@ -1540,14 +1540,14 @@ "last_modified" : 1775797786716, "fingerprint" : "6104ba7f216a937994d478ed07766ec28f48ad72fdd6620508535a1f877b8ddb", "metadata" : { - "palette" : { - "originalArgb8888" : [ -14671840, -11431408, -9326048, -802016, -3964416, -5086944, -789517, -810399, -1863087, -10403552, -5078447 ], - "convertedRgb565" : [ 8452, 21634, 30084, -2556, -15360, -19708, -2146, -2804, -7030, 25092, -19446 ] - }, "tile" : { "width" : 32, "height" : 32, "paletteIndices" : "AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAABAQEBAAAAAAEBAAAAAAAAAAAAAAAAAAAAAAAAAAEBAQICAwMBAQEBAwEAAAAAAAAAAAAAAAAAAAAAAAABBAQBAgIDAwMCAQMDAQAAAAAAAAAAAAAAAAAAAAAAAQUFBAQBAgIDAgICAwIBAAAAAAAAAAAAAAAAAAAAAAABBQEFBAUBAgICAgMCAQAAAAAAAAAAAAAAAAAAAAAAAAABBgEFBQUBAgECAgIBAAAAAAAAAAAAAAAAAAAAAAAAAAEGBwEFBAUBCAEBAQAAAAAAAAAAAAAAAAAAAAAAAAAAAQgBBwEEBQEJAQEAAAAAAAAAAAAAAAAAAAAAAAAAAAEICAEHCQEEBQEFAQAAAAAAAAAAAAAAAAAAAAAAAAAAAAEGCQkGBgEBAQEBAAAAAAAAAAAAAAAAAAAAAAAAAAABAQEBBgYGAQIDAgEBAAAAAAAAAAAAAAAAAAAAAAAAAAEJAQEBAQEBAgIBAQAAAAAAAAAAAAAAAAAAAAAAAAAAAAEBBwcDAgIBAQoKAQAAAAAAAAAAAAAAAAAAAAAAAAAAAQQBAwMDAgIBCQkBAAAAAAAAAAAAAAAAAAAAAAAAAAEBAgECAwMCAQEBAQEAAAAAAAAAAAAAAAAAAAAAAAABCwYBAgEBAQECAgEKAQAAAAAAAAAAAAAAAAAAAAAAAAELCgYBAgICAgEBAQEAAAAAAAAAAAAAAAAAAAAAAAAAAAEKCgoBAQEBAQEBAQAAAAAAAAAAAAAAAAAAAAAAAAAAAQEBAQEBAQEBAQEBAAAAAAAAAAAAAAAAAAAAAAAAAAAAAQEBAQEBAQEBAQAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAEBAQEBAQAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA==" + }, + "palette" : { + "originalArgb8888" : [ -14671840, -11431408, -9326048, -802016, -3964416, -5086944, -789517, -810399, -1863087, -10403552, -5078447 ], + "convertedRgb565" : [ 8452, 21634, 30084, -2556, -15360, -19708, -2146, -2804, -7030, 25092, -19446 ] } }, "diagnostics" : [ ] @@ -1602,14 +1602,14 @@ "last_modified" : 1776965154257, "fingerprint" : "8771c3e294d0edbc8dd3aaa6995a6db32166ae6bfb3e063170cc79b298d17e71", "metadata" : { - "palette" : { - "originalArgb8888" : [ -12019640 ], - "convertedRgb565" : [ 19657 ] - }, "tile" : { "width" : 8, "height" : 8, "paletteIndices" : "AQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQ==" + }, + "palette" : { + "originalArgb8888" : [ -12019640 ], + "convertedRgb565" : [ 19657 ] } }, "diagnostics" : [ ] @@ -1620,14 +1620,14 @@ "last_modified" : 1776965154257, "fingerprint" : "5d81eef8be13043330b42b546e10beed8ba00dfaa42df67477a8778c2b9484d7", "metadata" : { - "palette" : { - "originalArgb8888" : [ -12019640, -12552128, -14129088, -14133200, -14145496, -7835584, -5730208, -10465232 ], - "convertedRgb565" : [ 19657, 17352, 11080, 10950, 10565, -29816, -21364, 25222 ] - }, "tile" : { "width" : 8, "height" : 8, "paletteIndices" : "AQEBAQEBAQEBAQEBAQICAgECAgICAgICAgMEBQUFBQQDBAUGBgYGBQMEBQYGBwcIAwQFCAYGCAgBAwUFCAgIBw==" + }, + "palette" : { + "originalArgb8888" : [ -12019640, -12552128, -14129088, -14133200, -14145496, -7835584, -5730208, -10465232 ], + "convertedRgb565" : [ 19657, 17352, 11080, 10950, 10565, -29816, -21364, 25222 ] } }, "diagnostics" : [ ] @@ -1638,14 +1638,14 @@ "last_modified" : 1776965154258, "fingerprint" : "3250840c4fe08c134ea966ce7c8fcaccae2c2a45660d7173c5e262a2e5076548", "metadata" : { - "palette" : { - "originalArgb8888" : [ -12552128, -14133200, -14145496, -10465232, -5730208, -7835584 ], - "convertedRgb565" : [ 17352, 10950, 10565, 25222, -21364, -29816 ] - }, "tile" : { "width" : 8, "height" : 8, "paletteIndices" : "AQEBAQECAwMBAQEBAgMEBQEBAQIDBAUFAQIDAwQEBAQDAwYFBQUFBQQGBQUGBgYGBQUFBgYFBQUFBgYGBQUGBg==" + }, + "palette" : { + "originalArgb8888" : [ -12552128, -14133200, -14145496, -10465232, -5730208, -7835584 ], + "convertedRgb565" : [ 17352, 10950, 10565, 25222, -21364, -29816 ] } }, "diagnostics" : [ ] @@ -1656,14 +1656,14 @@ "last_modified" : 1776965154258, "fingerprint" : "fe3ab2b7eb3b10a042de14484d53e718e6b505edb1ad19053668565bfe3a8f25", "metadata" : { - "palette" : { - "originalArgb8888" : [ -14145496, -14133200, -12552128, -5730208, -10465232, -7835584 ], - "convertedRgb565" : [ 10565, 10950, 17352, -21364, 25222, -29816 ] - }, "tile" : { "width" : 8, "height" : 8, "paletteIndices" : "AQECAwMDAwMEBQECAwMDAwQEBQECAwMDBQUFBQEBAgMEBAQEBAYBAQYGBgYEBAYFBAQEBgYEBAQGBgQEBgYGBA==" + }, + "palette" : { + "originalArgb8888" : [ -14145496, -14133200, -12552128, -5730208, -10465232, -7835584 ], + "convertedRgb565" : [ 10565, 10950, 17352, -21364, 25222, -29816 ] } }, "diagnostics" : [ ] @@ -1674,14 +1674,14 @@ "last_modified" : 1776965154259, "fingerprint" : "7fcbf90e1e9a69d6ce3be80ea1901d66c9992f68dc72e4c636dcd2ad52fa2898", "metadata" : { - "palette" : { - "originalArgb8888" : [ -12019640, -12552128, -14133200, -14145496, -14129088, -7835584, -10465232, -5730208 ], - "convertedRgb565" : [ 19657, 17352, 10950, 10565, 11080, -29816, 25222, -21364 ] - }, "tile" : { "width" : 8, "height" : 8, "paletteIndices" : "AQEBAQEBAQECAgIBAQEBAQICAgICAgIBAwQEBAQDBQIEBgYGBgQDBQcICAYGBAMFBwcGBgcEAwUIBwcHBAQFAQ==" + }, + "palette" : { + "originalArgb8888" : [ -12019640, -12552128, -14133200, -14145496, -14129088, -7835584, -10465232, -5730208 ], + "convertedRgb565" : [ 19657, 17352, 10950, 10565, 11080, -29816, 25222, -21364 ] } }, "diagnostics" : [ ] @@ -1692,14 +1692,14 @@ "last_modified" : 1776965154259, "fingerprint" : "451fc8d646049944d5aa7c7dc254636eec0151aaff6e2051059304b9d6ebc31e", "metadata" : { - "palette" : { - "originalArgb8888" : [ -12019640, -14129088, -14133200, -14145496, -10465232, -5730208, -7835584 ], - "convertedRgb565" : [ 19657, 11080, 10950, 10565, 25222, -21364, -29816 ] - }, "tile" : { "width" : 8, "height" : 8, "paletteIndices" : "AQIDBAQFBgYBAQIDBAYGBwEBAQMEBgcHAQEBBAQGBwcBAQQFBAYHBwEEBwUEBgcHBAcGBQQGBwcEBwYFBAYHBw==" + }, + "palette" : { + "originalArgb8888" : [ -12019640, -14129088, -14133200, -14145496, -10465232, -5730208, -7835584 ], + "convertedRgb565" : [ 19657, 11080, 10950, 10565, 25222, -21364, -29816 ] } }, "diagnostics" : [ ] @@ -1710,14 +1710,14 @@ "last_modified" : 1776965154260, "fingerprint" : "aa757df4600823ec6655235a1081061777124ccee74b31481bbe402e53635f53", "metadata" : { - "palette" : { - "originalArgb8888" : [ -7835584, -5730208, -10465232, -14145496 ], - "convertedRgb565" : [ -29816, -21364, 25222, 10565 ] - }, "tile" : { "width" : 8, "height" : 8, "paletteIndices" : "AQECAwMBAQEBAgIBAwMBAgICAQEBAwMCAgIBAQIDBAMCAgEBAgMEBAICAQECAwQEAgIBAQIDBAMCAgIBAwQDAg==" + }, + "palette" : { + "originalArgb8888" : [ -7835584, -5730208, -10465232, -14145496 ], + "convertedRgb565" : [ -29816, -21364, 25222, 10565 ] } }, "diagnostics" : [ ] @@ -1728,14 +1728,14 @@ "last_modified" : 1776965154260, "fingerprint" : "38162157f5685cce25b835d3a2caee3465fd2ec3ee5db2a5089d7d5ae5ea3bb7", "metadata" : { - "palette" : { - "originalArgb8888" : [ -7835584, -10465232, -5730208, -14145496 ], - "convertedRgb565" : [ -29816, 25222, -21364, 10565 ] - }, "tile" : { "width" : 8, "height" : 8, "paletteIndices" : "AQEBAgIDAQEDAQICAQMDAQMCAgEBAQMDAgQCAwEBAwMEBAIDAQEDAwQEAgMBAQMDAgQCAwEBAwMDAgQCAQMDAw==" + }, + "palette" : { + "originalArgb8888" : [ -7835584, -10465232, -5730208, -14145496 ], + "convertedRgb565" : [ -29816, 25222, -21364, 10565 ] } }, "diagnostics" : [ ] @@ -1746,14 +1746,14 @@ "last_modified" : 1776965154260, "fingerprint" : "8cab5b3d553af9ed371bd19fc624763accc90e5d926d300ba31dd8d9d6bab803", "metadata" : { - "palette" : { - "originalArgb8888" : [ -5730208, -10465232, -14145496, -14133200, -14129088, -12019640, -7835584 ], - "convertedRgb565" : [ -21364, 25222, 10565, 10950, 11080, 19657, -29816 ] - }, "tile" : { "width" : 8, "height" : 8, "paletteIndices" : "AQECAwMEBQYHAQEDBAUGBgcHAQMEBgYGBwcBAwMGBgYHBwEDAgMGBgcHAQMCBwMGBwcBAwIBBwMHBwEDAgEHAw==" + }, + "palette" : { + "originalArgb8888" : [ -5730208, -10465232, -14145496, -14133200, -14129088, -12019640, -7835584 ], + "convertedRgb565" : [ -21364, 25222, 10565, 10950, 11080, 19657, -29816 ] } }, "diagnostics" : [ ] @@ -1764,14 +1764,14 @@ "last_modified" : 1776965154261, "fingerprint" : "d9ff5a6df0f65f5fcfb8f22376beeb266d429e2c6e9c82f51c12bc6ee4c3fcdc", "metadata" : { - "palette" : { - "originalArgb8888" : [ -14145496, -10465232, -7835584, -5730208, -14133200, -14129088, -12019640 ], - "convertedRgb565" : [ 10565, 25222, -29816, -21364, 10950, 11080, 19657 ] - }, "tile" : { "width" : 8, "height" : 8, "paletteIndices" : "AQIDAgIBBAMFAQECAgEEBAUGBQECAgEEBwYFBQECAQEHBwYGBQEBAgcHBwYFAQMDBwcHBwEBAwMHBwcFAQICAw==" + }, + "palette" : { + "originalArgb8888" : [ -14145496, -10465232, -7835584, -5730208, -14133200, -14129088, -12019640 ], + "convertedRgb565" : [ 10565, 25222, -29816, -21364, 10950, 11080, 19657 ] } }, "diagnostics" : [ ] @@ -1782,14 +1782,14 @@ "last_modified" : 1776965154261, "fingerprint" : "b9ff45c77f7779a6acebcc537c2ddac0e27e91162b656a04dc4772ec5f24fc26", "metadata" : { - "palette" : { - "originalArgb8888" : [ -7835584, -5730208, -10465232, -14145496 ], - "convertedRgb565" : [ -29816, -21364, 25222, 10565 ] - }, "tile" : { "width" : 8, "height" : 8, "paletteIndices" : "AQICAwMBAQIBAQMDAgIBAQIBAQEBAgIBAgICAgEBAgIEAwMCAgEBAQMEAwMCAgEBAQMEAwMDAgIBAwMEAwMDAw==" + }, + "palette" : { + "originalArgb8888" : [ -7835584, -5730208, -10465232, -14145496 ], + "convertedRgb565" : [ -29816, -21364, 25222, 10565 ] } }, "diagnostics" : [ ] @@ -1800,14 +1800,14 @@ "last_modified" : 1776965154261, "fingerprint" : "43f370324fedccda888d49409e2a64f182f08b4143b4bdd5bafaf498feebd21a", "metadata" : { - "palette" : { - "originalArgb8888" : [ -5730208, -7835584, -10465232, -14145496 ], - "convertedRgb565" : [ -21364, -29816, 25222, 10565 ] - }, "tile" : { "width" : 8, "height" : 8, "paletteIndices" : "AQICAwMBAQICAgEBAwMCAgIBAQICAgIBAQECAgEBAQECAgIBAQMDBAICAQEDAwQDAQEDAwMEAwIDAwMDBAMDAg==" + }, + "palette" : { + "originalArgb8888" : [ -5730208, -7835584, -10465232, -14145496 ], + "convertedRgb565" : [ -21364, -29816, 25222, 10565 ] } }, "diagnostics" : [ ] @@ -1818,14 +1818,14 @@ "last_modified" : 1776965154262, "fingerprint" : "cb047e655f4e196f22ca0048149df5dcb959f895faeaeb94920182d4a2d16b38", "metadata" : { - "palette" : { - "originalArgb8888" : [ -7835584, -5730208, -14145496, -10465232, -14133200, -14129088, -12019640 ], - "convertedRgb565" : [ -29816, -21364, 10565, 25222, 10950, 11080, 19657 ] - }, "tile" : { "width" : 8, "height" : 8, "paletteIndices" : "AQIDBAQBBAMCAgMEBAMDBQIDBAQDBQYFAwMEAwUFBgcEAwMFBgYHBwEBAwUGBwcHAQEDAwcHBwcBBAQDBQcHBw==" + }, + "palette" : { + "originalArgb8888" : [ -7835584, -5730208, -14145496, -10465232, -14133200, -14129088, -12019640 ], + "convertedRgb565" : [ -29816, -21364, 10565, 25222, 10950, 11080, 19657 ] } }, "diagnostics" : [ ] @@ -1836,14 +1836,14 @@ "last_modified" : 1776965154262, "fingerprint" : "25eba17b67dd5159f5fb9d3edd531d54a44d1c76f997385840dac53517b98886", "metadata" : { - "palette" : { - "originalArgb8888" : [ -12019640, -14145496, -7835584, -10465232, -14133200, -14129088 ], - "convertedRgb565" : [ 19657, 10565, -29816, 25222, 10950, 11080 ] - }, "tile" : { "width" : 8, "height" : 8, "paletteIndices" : "AQEBAgMDBAQBAQIDAwMDBAEBAgMDAwMEAQECAwMEAgQBAQIEAgUFAgEBBQUGBQYFAQEBAQEGAQYBAQEBAQEBAQ==" + }, + "palette" : { + "originalArgb8888" : [ -12019640, -14145496, -7835584, -10465232, -14133200, -14129088 ], + "convertedRgb565" : [ 19657, 10565, -29816, 25222, 10950, 11080 ] } }, "diagnostics" : [ ] @@ -1854,14 +1854,14 @@ "last_modified" : 1776965154262, "fingerprint" : "32ca96c14290de8009fd2db623f55514bed2345b7d5881a80dd3fe6235012854", "metadata" : { - "palette" : { - "originalArgb8888" : [ -10465232, -14145496, -14133200, -7835584, -14129088, -12019640 ], - "convertedRgb565" : [ 25222, 10565, 10950, -29816, 11080, 19657 ] - }, "tile" : { "width" : 8, "height" : 8, "paletteIndices" : "AQEBAgEBAgICAQICAQIBAQICAwICAQEEAgMDAwIBAQQDAwUDAwIBAQUFBgUFAgEEBgYGBgYDAgEGBgYGBgYDAg==" + }, + "palette" : { + "originalArgb8888" : [ -10465232, -14145496, -14133200, -7835584, -14129088, -12019640 ], + "convertedRgb565" : [ 25222, 10565, 10950, -29816, 11080, 19657 ] } }, "diagnostics" : [ ] @@ -1872,14 +1872,14 @@ "last_modified" : 1776965154263, "fingerprint" : "7a093fe00c805bcf38d4facff14a6d4c2b8baeaa2d553fa8d3db9f2d76b32f3b", "metadata" : { - "palette" : { - "originalArgb8888" : [ -14145496, -10465232, -7835584, -14133200, -14129088, -12019640 ], - "convertedRgb565" : [ 10565, 25222, -29816, 10950, 11080, 19657 ] - }, "tile" : { "width" : 8, "height" : 8, "paletteIndices" : "AQECAgECAgICAgECAQECAQMCAgEBBAEBAwICAQQEBAECAgEEBAUEBAMCAQUFBgUFAgEEBgYGBgYBBAYGBgYGBg==" + }, + "palette" : { + "originalArgb8888" : [ -14145496, -10465232, -7835584, -14133200, -14129088, -12019640 ], + "convertedRgb565" : [ 10565, 25222, -29816, 10950, 11080, 19657 ] } }, "diagnostics" : [ ] @@ -1890,14 +1890,14 @@ "last_modified" : 1776965154263, "fingerprint" : "77c5277220421226d16f58b1bcfb4eaf157fa4f6c740c5aaebefaf88fb91c22e", "metadata" : { - "palette" : { - "originalArgb8888" : [ -10465232, -7835584, -14145496, -12019640, -14133200, -14129088 ], - "convertedRgb565" : [ 25222, -29816, 10565, 19657, 10950, 11080 ] - }, "tile" : { "width" : 8, "height" : 8, "paletteIndices" : "AQECAgMEBAQBAgICAgMEBAECAgICAwQEAQMBAgIDBAQDBQUDAQMEBAUGBQYFBQQEBgQGBAQEBAQEBAQEBAQEBA==" + }, + "palette" : { + "originalArgb8888" : [ -10465232, -7835584, -14145496, -12019640, -14133200, -14129088 ], + "convertedRgb565" : [ 25222, -29816, 10565, 19657, 10950, 11080 ] } }, "diagnostics" : [ ] diff --git a/test-projects/main/src/main.pbs b/test-projects/main/src/main.pbs index ce88eaf8..1cdf6722 100644 --- a/test-projects/main/src/main.pbs +++ b/test-projects/main/src/main.pbs @@ -15,6 +15,8 @@ declare global camera_mult: int = 1; declare const MAX_FRAMES: int = 4; declare const CAMERA_SPEED: int = 1; +declare struct Bla (a: int) {} + [Init] fn init() -> void { @@ -25,6 +27,7 @@ fn init() -> void camera_x = 0; camera_mult = 1; Composer.bind_scene(0); + let bla: Bla = new Bla(1); } [Frame] @@ -55,9 +58,8 @@ fn frame() -> void } } - - let touch : InputTouch = Input.touch(); + let pad : InputPad = Input.pad(); if (touch.button().released()) { @@ -93,15 +95,15 @@ fn frame() -> void let b : int = 15; let total : int = a + b; - if (Input.pad().a().pressed()) + if (pad.a().pressed()) { total += 25; } - else if (Input.pad().b().pressed()) + else if (pad.b().pressed()) { total += 5; } - else if (Input.pad().x().pressed()) + else if (pad.x().pressed()) { total -= 10; } -- 2.47.2 From 0e6a2cd5bcf97670257b114782c59278495847ef Mon Sep 17 00:00:00 2001 From: bQUARKz Date: Thu, 7 May 2026 14:53:33 +0100 Subject: [PATCH 31/37] housekeeping --- .../.backups/index.ndjson.20260331-004213.bak | 12 -- .../.backups/index.ndjson.20260507-142320.bak | 35 ++++ discussion/index.ndjson | 6 +- ...d-lsp-boundary-and-protocol-containment.md | 106 ++++++++++ ...laries-with-declarative-host-projection.md | 90 ++++++++ ...0035-studio-new-lsp-api-and-v1-boundary.md | 128 ------------ ...nd-semantic-host-projection-flexibility.md | 85 -------- ...0032-studio-new-lsp-api-and-v1-boundary.md | 196 ------------------ ...nd-semantic-host-projection-flexibility.md | 112 ---------- ...065-lsp-boundary-and-module-scaffolding.md | 118 ----------- ...t-scoped-lsp-server-lifecycle-in-studio.md | 103 --------- ...ompiler-backed-dumb-lsp-server-baseline.md | 100 --------- ...ntend-semantic-host-projection-contract.md | 119 ----------- ...-lsp-semantic-host-projection-transport.md | 107 ---------- ...vscode-semantic-host-projection-adapter.md | 109 ---------- .../themes/pbs/semantic-highlighting.css | 111 ---------- 16 files changed, 234 insertions(+), 1303 deletions(-) delete mode 100644 discussion/.backups/index.ndjson.20260331-004213.bak create mode 100644 discussion/.backups/index.ndjson.20260507-142320.bak create mode 100644 discussion/lessons/DSC-0032-studio-new-lsp-api-and-v1-boundary/LSN-0047-project-scoped-lsp-boundary-and-protocol-containment.md create mode 100644 discussion/lessons/DSC-0034-frontend-semantic-host-projection-flexibility/LSN-0048-frontend-owned-semantic-vocabularies-with-declarative-host-projection.md delete mode 100644 discussion/workflow/agendas/AGD-0035-studio-new-lsp-api-and-v1-boundary.md delete mode 100644 discussion/workflow/agendas/AGD-0037-frontend-semantic-host-projection-flexibility.md delete mode 100644 discussion/workflow/decisions/DEC-0032-studio-new-lsp-api-and-v1-boundary.md delete mode 100644 discussion/workflow/decisions/DEC-0034-frontend-semantic-host-projection-flexibility.md delete mode 100644 discussion/workflow/plans/PLN-0065-lsp-boundary-and-module-scaffolding.md delete mode 100644 discussion/workflow/plans/PLN-0066-project-scoped-lsp-server-lifecycle-in-studio.md delete mode 100644 discussion/workflow/plans/PLN-0067-compiler-backed-dumb-lsp-server-baseline.md delete mode 100644 discussion/workflow/plans/PLN-0072-frontend-semantic-host-projection-contract.md delete mode 100644 discussion/workflow/plans/PLN-0073-lsp-semantic-host-projection-transport.md delete mode 100644 discussion/workflow/plans/PLN-0074-vscode-semantic-host-projection-adapter.md delete mode 100644 prometeu-compiler/frontends/prometeu-frontend-pbs/src/main/resources/themes/pbs/semantic-highlighting.css diff --git a/discussion/.backups/index.ndjson.20260331-004213.bak b/discussion/.backups/index.ndjson.20260331-004213.bak deleted file mode 100644 index bf3215ca..00000000 --- a/discussion/.backups/index.ndjson.20260331-004213.bak +++ /dev/null @@ -1,12 +0,0 @@ -{"type":"meta","next_id":{"DSC":12,"AGD":12,"DEC":9,"PLN":15,"LSN":26,"CLSN":1}} -{"type":"discussion","id":"DSC-0001","status":"done","ticket":"studio-docs-import","title":"Import docs/studio into discussion-framework artifacts","created_at":"2026-03-26","updated_at":"2026-03-26","tags":["studio","migration","discussion-framework","docs-import"],"agendas":[],"decisions":[],"plans":[],"lessons":[{"id":"LSN-0001","file":"discussion/lessons/DSC-0001-studio-docs-import/LSN-0001-assets-workspace-execution-wave-legacy.md","status":"done","created_at":"2026-03-26","updated_at":"2026-03-26"},{"id":"LSN-0002","file":"discussion/lessons/DSC-0001-studio-docs-import/LSN-0002-bank-composition-editor-legacy.md","status":"done","created_at":"2026-03-26","updated_at":"2026-03-26"},{"id":"LSN-0003","file":"discussion/lessons/DSC-0001-studio-docs-import/LSN-0003-mental-model-asset-mutations-legacy.md","status":"done","created_at":"2026-03-26","updated_at":"2026-03-26"},{"id":"LSN-0004","file":"discussion/lessons/DSC-0001-studio-docs-import/LSN-0004-mental-model-assets-workspace-legacy.md","status":"done","created_at":"2026-03-26","updated_at":"2026-03-26"},{"id":"LSN-0005","file":"discussion/lessons/DSC-0001-studio-docs-import/LSN-0005-mental-model-studio-events-and-components-legacy.md","status":"done","created_at":"2026-03-26","updated_at":"2026-03-26"},{"id":"LSN-0006","file":"discussion/lessons/DSC-0001-studio-docs-import/LSN-0006-mental-model-studio-shell-legacy.md","status":"done","created_at":"2026-03-26","updated_at":"2026-03-26"},{"id":"LSN-0007","file":"discussion/lessons/DSC-0001-studio-docs-import/LSN-0007-pack-wizard-shell-legacy.md","status":"done","created_at":"2026-03-26","updated_at":"2026-03-26"},{"id":"LSN-0008","file":"discussion/lessons/DSC-0001-studio-docs-import/LSN-0008-project-scoped-state-and-activity-legacy.md","status":"done","created_at":"2026-03-26","updated_at":"2026-03-26"},{"id":"LSN-0016","file":"discussion/lessons/DSC-0001-studio-docs-import/LSN-0016-studio-docs-import-pattern.md","status":"done","created_at":"2026-03-26","updated_at":"2026-03-26"}]} -{"type":"discussion","id":"DSC-0002","status":"open","ticket":"palette-management-in-studio","title":"Palette Management in Studio","created_at":"2026-03-26","updated_at":"2026-03-26","tags":["studio","legacy-import","palette-management","tile-bank","packer-boundary"],"agendas":[{"id":"AGD-0002","file":"AGD-0002-palette-management-in-studio.md","status":"open","created_at":"2026-03-26","updated_at":"2026-03-26"}],"decisions":[],"plans":[],"lessons":[]} -{"type":"discussion","id":"DSC-0003","status":"done","ticket":"packer-docs-import","title":"Import docs/packer into discussion-framework artifacts","created_at":"2026-03-26","updated_at":"2026-03-26","tags":["packer","migration","discussion-framework","docs-import"],"agendas":[],"decisions":[],"plans":[],"lessons":[{"id":"LSN-0009","file":"discussion/lessons/DSC-0003-packer-docs-import/LSN-0009-mental-model-packer-legacy.md","status":"done","created_at":"2026-03-26","updated_at":"2026-03-26"},{"id":"LSN-0010","file":"discussion/lessons/DSC-0003-packer-docs-import/LSN-0010-asset-identity-and-runtime-contract-legacy.md","status":"done","created_at":"2026-03-26","updated_at":"2026-03-26"},{"id":"LSN-0011","file":"discussion/lessons/DSC-0003-packer-docs-import/LSN-0011-foundations-workspace-runtime-and-build-legacy.md","status":"done","created_at":"2026-03-26","updated_at":"2026-03-26"},{"id":"LSN-0012","file":"discussion/lessons/DSC-0003-packer-docs-import/LSN-0012-runtime-ownership-and-studio-boundary-legacy.md","status":"done","created_at":"2026-03-26","updated_at":"2026-03-26"},{"id":"LSN-0013","file":"discussion/lessons/DSC-0003-packer-docs-import/LSN-0013-metadata-convergence-and-runtime-sink-legacy.md","status":"done","created_at":"2026-03-26","updated_at":"2026-03-26"},{"id":"LSN-0014","file":"discussion/lessons/DSC-0003-packer-docs-import/LSN-0014-pack-wizard-summary-validation-and-pack-execution-legacy.md","status":"done","created_at":"2026-03-26","updated_at":"2026-03-26"},{"id":"LSN-0015","file":"discussion/lessons/DSC-0003-packer-docs-import/LSN-0015-tile-bank-packing-contract-legacy.md","status":"done","created_at":"2026-03-26","updated_at":"2026-03-26"},{"id":"LSN-0017","file":"discussion/lessons/DSC-0003-packer-docs-import/LSN-0017-packer-docs-import-pattern.md","status":"done","created_at":"2026-03-26","updated_at":"2026-03-26"}]} -{"type":"discussion","id":"DSC-0004","status":"open","ticket":"tilemap-and-metatile-runtime-binary-layout","title":"Tilemap and Metatile Runtime Binary Layout","created_at":"2026-03-26","updated_at":"2026-03-26","tags":["packer","legacy-import","tilemap","metatile","runtime-layout"],"agendas":[{"id":"AGD-0004","file":"AGD-0004-tilemap-and-metatile-runtime-binary-layout.md","status":"open","created_at":"2026-03-26","updated_at":"2026-03-26"}],"decisions":[],"plans":[],"lessons":[]} -{"type":"discussion","id":"DSC-0005","status":"open","ticket":"variable-tile-bank-palette-serialization","title":"Variable Tile Bank Palette Serialization","created_at":"2026-03-26","updated_at":"2026-03-26","tags":["packer","legacy-import","tile-bank","palette-serialization","versioning"],"agendas":[{"id":"AGD-0005","file":"AGD-0005-variable-tile-bank-palette-serialization.md","status":"open","created_at":"2026-03-26","updated_at":"2026-03-26"}],"decisions":[],"plans":[],"lessons":[]} -{"type":"discussion","id":"DSC-0006","status":"done","ticket":"pbs-game-facing-asset-refs-and-call-result-discard","title":"PBS Game-Facing Asset References and Ignored Call Result Lowering","created_at":"2026-03-27","updated_at":"2026-03-30","tags":["compiler","pbs","ergonomics","lowering","runtime","asset-identity","expression-statements"],"agendas":[],"decisions":[],"plans":[],"lessons":[{"id":"LSN-0024","file":"discussion/lessons/DSC-0006-pbs-game-facing-asset-refs-and-call-result-discard/LSN-0024-addressable-surface-host-metadata-and-ignored-value-discipline.md","status":"done","created_at":"2026-03-30","updated_at":"2026-03-30"}]} -{"type":"discussion","id":"DSC-0007","status":"done","ticket":"pbs-learn-to-discussion-lessons-migration","title":"Migrate PBS Learn Documents into Discussion Lessons","created_at":"2026-03-27","updated_at":"2026-03-27","tags":["compiler","pbs","migration","discussion-framework","lessons","learn-prune"],"agendas":[],"decisions":[],"plans":[],"lessons":[{"id":"LSN-0018","file":"discussion/lessons/DSC-0007-pbs-learn-to-discussion-lessons-migration/LSN-0018-pbs-ast-and-parser-contract-legacy.md","status":"done","created_at":"2026-03-27","updated_at":"2026-03-27"},{"id":"LSN-0019","file":"discussion/lessons/DSC-0007-pbs-learn-to-discussion-lessons-migration/LSN-0019-pbs-name-resolution-and-linking-legacy.md","status":"done","created_at":"2026-03-27","updated_at":"2026-03-27"},{"id":"LSN-0020","file":"discussion/lessons/DSC-0007-pbs-learn-to-discussion-lessons-migration/LSN-0020-pbs-runtime-values-identity-memory-boundaries-legacy.md","status":"done","created_at":"2026-03-27","updated_at":"2026-03-27"},{"id":"LSN-0021","file":"discussion/lessons/DSC-0007-pbs-learn-to-discussion-lessons-migration/LSN-0021-pbs-diagnostics-and-conformance-governance-legacy.md","status":"done","created_at":"2026-03-27","updated_at":"2026-03-27"},{"id":"LSN-0022","file":"discussion/lessons/DSC-0007-pbs-learn-to-discussion-lessons-migration/LSN-0022-pbs-globals-lifecycle-and-published-entrypoint-legacy.md","status":"done","created_at":"2026-03-27","updated_at":"2026-03-27"}]} -{"type":"discussion","id":"DSC-0008","status":"done","ticket":"pbs-low-level-asset-manager-surface","title":"PBS Low-Level Asset Manager Surface for Runtime AssetManager","created_at":"2026-03-27","updated_at":"2026-03-27","tags":["compiler","pbs","runtime","asset-manager","host-abi","stdlib","asset"],"agendas":[],"decisions":[],"plans":[],"lessons":[{"id":"LSN-0023","file":"discussion/lessons/DSC-0008-pbs-low-level-asset-manager-surface/LSN-0023-lowassets-runtime-aligned-sdk-surface.md","status":"done","created_at":"2026-03-27","updated_at":"2026-03-27"}]} -{"type":"discussion","id":"DSC-0009","status":"open","ticket":"studio-debugger-workspace-integration","title":"Integrate ../debugger into Studio as a dedicated workspace","created_at":"2026-03-30","updated_at":"2026-03-30","tags":["studio","debugger","workspace","integration","shell"],"agendas":[{"id":"AGD-0009","file":"AGD-0009-studio-debugger-workspace-integration.md","status":"open","created_at":"2026-03-30","updated_at":"2026-03-30"}],"decisions":[],"plans":[],"lessons":[]} -{"type":"discussion","id":"DSC-0010","status":"in_progress","ticket":"studio-code-editor-workspace-foundations","title":"Establish Code Editor workspace foundations in Studio without LSP","created_at":"2026-03-30","updated_at":"2026-03-30","tags":["studio","editor","workspace","multi-frontend","lsp-deferred"],"agendas":[{"id":"AGD-0010","file":"AGD-0010-studio-code-editor-workspace-foundations.md","status":"accepted","created_at":"2026-03-30","updated_at":"2026-03-30"}],"decisions":[{"id":"DEC-0008","file":"DEC-0008-studio-code-editor-read-only-workspace-foundations.md","status":"accepted","created_at":"2026-03-30","updated_at":"2026-03-30","ref_agenda":"AGD-0010"}],"plans":[{"id":"PLN-0012","file":"PLN-0012-studio-code-editor-spec-propagation.md","status":"done","created_at":"2026-03-30","updated_at":"2026-03-30","ref_decisions":["DEC-0008"]},{"id":"PLN-0013","file":"PLN-0013-editor-workspace-layout-and-passive-surfaces.md","status":"done","created_at":"2026-03-30","updated_at":"2026-03-30","ref_decisions":["DEC-0008"]},{"id":"PLN-0014","file":"PLN-0014-project-navigator-snapshot-and-read-only-file-opening.md","status":"done","created_at":"2026-03-30","updated_at":"2026-03-30","ref_decisions":["DEC-0008"]}],"lessons":[]} -{"type":"discussion","id":"DSC-0011","status":"done","ticket":"compiler-analyze-compile-build-pipeline-split","title":"Split compiler pipeline into analyze, compile, and build entrypoints","created_at":"2026-03-30","updated_at":"2026-03-30","tags":["compiler","pipeline","artifacts","build","analysis"],"agendas":[],"decisions":[],"plans":[],"lessons":[{"id":"LSN-0025","file":"discussion/lessons/DSC-0011-compiler-analyze-compile-build-pipeline-split/LSN-0025-compiler-pipeline-entrypoints-and-result-boundaries.md","status":"done","created_at":"2026-03-30","updated_at":"2026-03-30"}]} diff --git a/discussion/.backups/index.ndjson.20260507-142320.bak b/discussion/.backups/index.ndjson.20260507-142320.bak new file mode 100644 index 00000000..f17e173d --- /dev/null +++ b/discussion/.backups/index.ndjson.20260507-142320.bak @@ -0,0 +1,35 @@ +{"type":"meta","next_id":{"DSC":35,"AGD":38,"DEC":35,"PLN":75,"LSN":47,"CLSN":1}} +{"type":"discussion","id":"DSC-0034","status":"in_progress","ticket":"frontend-semantic-host-projection-flexibility","title":"Frontend semantic vocabulary flexibility and declarative host projection","created_at":"2026-05-06","updated_at":"2026-05-06","tags":["compiler","compiler-general","frontend","semantics","vscode","host-projection","lsp"],"agendas":[{"id":"AGD-0037","file":"AGD-0037-frontend-semantic-host-projection-flexibility.md","status":"accepted","created_at":"2026-05-06","updated_at":"2026-05-06"}],"decisions":[{"id":"DEC-0034","file":"DEC-0034-frontend-semantic-host-projection-flexibility.md","status":"accepted","created_at":"2026-05-06","updated_at":"2026-05-06","ref_agenda":"AGD-0037"}],"plans":[{"id":"PLN-0072","file":"PLN-0072-frontend-semantic-host-projection-contract.md","status":"done","created_at":"2026-05-06","updated_at":"2026-05-06","ref_decisions":["DEC-0034"]},{"id":"PLN-0073","file":"PLN-0073-lsp-semantic-host-projection-transport.md","status":"done","created_at":"2026-05-06","updated_at":"2026-05-06","ref_decisions":["DEC-0034"]},{"id":"PLN-0074","file":"PLN-0074-vscode-semantic-host-projection-adapter.md","status":"done","created_at":"2026-05-06","updated_at":"2026-05-06","ref_decisions":["DEC-0034"]}],"lessons":[]} +{"type":"discussion","id":"DSC-0033","status":"in_progress","ticket":"frontend-visual-theme-spec-and-css-retirement","title":"Frontend visual theme spec and retirement of host-consumed semantic CSS","created_at":"2026-05-06","updated_at":"2026-05-06","tags":["compiler","compiler-general","frontend","presentation","theming","studio","vscode","lsp","pbs"],"agendas":[{"id":"AGD-0036","file":"AGD-0036-frontend-visual-theme-spec-and-css-retirement.md","status":"accepted","created_at":"2026-05-06","updated_at":"2026-05-06"}],"decisions":[{"id":"DEC-0033","file":"DEC-0033-frontend-visual-theme-spec-and-css-retirement.md","status":"accepted","created_at":"2026-05-06","updated_at":"2026-05-06","ref_agenda":"AGD-0036"}],"plans":[{"id":"PLN-0068","file":"PLN-0068-frontend-visual-contract-and-pbs-migration.md","status":"open","created_at":"2026-05-06","updated_at":"2026-05-06","ref_decisions":["DEC-0033"]},{"id":"PLN-0069","file":"PLN-0069-lsp-visual-theme-transport-and-selection.md","status":"open","created_at":"2026-05-06","updated_at":"2026-05-06","ref_decisions":["DEC-0033"]},{"id":"PLN-0070","file":"PLN-0070-studio-visual-theme-adapter-and-css-retirement.md","status":"open","created_at":"2026-05-06","updated_at":"2026-05-06","ref_decisions":["DEC-0033"]},{"id":"PLN-0071","file":"PLN-0071-vscode-dynamic-theme-translation-adapter.md","status":"open","created_at":"2026-05-06","updated_at":"2026-05-06","ref_decisions":["DEC-0033"]}],"lessons":[]} +{"type":"discussion","id":"DSC-0032","status":"in_progress","ticket":"studio-new-lsp-api-and-v1-boundary","title":"Novo boundary entre lsp-api, lsp-v1 e a extensao VS Code","created_at":"2026-05-05","updated_at":"2026-05-05","tags":["studio","lsp","vscode","protocol","api","boundary"],"agendas":[{"id":"AGD-0035","file":"AGD-0035-studio-new-lsp-api-and-v1-boundary.md","status":"accepted","created_at":"2026-05-05","updated_at":"2026-05-05"}],"decisions":[{"id":"DEC-0032","file":"DEC-0032-studio-new-lsp-api-and-v1-boundary.md","status":"accepted","created_at":"2026-05-05","updated_at":"2026-05-05","ref_agenda":"AGD-0035"}],"plans":[{"id":"PLN-0065","file":"PLN-0065-lsp-boundary-and-module-scaffolding.md","status":"done","created_at":"2026-05-05","updated_at":"2026-05-05","ref_decisions":["DEC-0032"]},{"id":"PLN-0066","file":"PLN-0066-project-scoped-lsp-server-lifecycle-in-studio.md","status":"done","created_at":"2026-05-05","updated_at":"2026-05-05","ref_decisions":["DEC-0032"]},{"id":"PLN-0067","file":"PLN-0067-compiler-backed-dumb-lsp-server-baseline.md","status":"done","created_at":"2026-05-05","updated_at":"2026-05-05","ref_decisions":["DEC-0032"]}],"lessons":[]} +{"type":"discussion","id":"DSC-0031","status":"in_progress","ticket":"studio-editor-workspace-cleanup","title":"Limpeza completa do Workspace Editor do Studio e remoção dos acoplamentos legados","created_at":"2026-05-05","updated_at":"2026-05-05","tags":["studio","editor","cleanup","vfs","lsp","migration"],"agendas":[{"id":"AGD-0034","file":"AGD-0034-vscode-editor-migration-feasibility.md","status":"accepted","created_at":"2026-05-05","updated_at":"2026-05-05"}],"decisions":[{"id":"DEC-0031","file":"DEC-0031-studio-editor-workspace-cleanup.md","status":"in_progress","created_at":"2026-05-05","updated_at":"2026-05-05","ref_agenda":"AGD-0034"}],"plans":[{"id":"PLN-0062","file":"PLN-0062-shell-session-and-state-cleanup-after-editor-removal.md","status":"done","created_at":"2026-05-05","updated_at":"2026-05-05","ref_decisions":["DEC-0031"]},{"id":"PLN-0063","file":"PLN-0063-legacy-lsp-and-vfs-module-removal-with-runtime-preservation.md","status":"done","created_at":"2026-05-05","updated_at":"2026-05-05","ref_decisions":["DEC-0031"]},{"id":"PLN-0064","file":"PLN-0064-normative-test-and-lesson-cleanup-for-editor-stack-removal.md","status":"done","created_at":"2026-05-05","updated_at":"2026-05-05","ref_decisions":["DEC-0031"]}],"lessons":[]} +{"type":"discussion","id":"DSC-0030","status":"done","ticket":"studio-scene-pack-runtime-binary-contract","title":"Studio scene pack contract for runtime SCENE binary payload","created_at":"2026-04-24","updated_at":"2026-05-01","tags":["studio","packer","runtime","scene","asset-pack","binary-format","tiled"],"agendas":[],"decisions":[],"plans":[],"lessons":[{"id":"LSN-0046","file":"discussion/lessons/DSC-0030-studio-scene-pack-runtime-binary-contract/LSN-0046-canonical-scene-owns-editorial-truth-while-pack-stays-request-driven.md","status":"done","created_at":"2026-05-01","updated_at":"2026-05-01"}]} +{"type":"discussion","id":"DSC-0029","status":"done","ticket":"studio-frame-composer-syscall-and-sprite-alignment","title":"Studio Alignment with Runtime FrameComposer Syscalls and Sprite Composition","created_at":"2026-04-18","updated_at":"2026-04-18","tags":["studio","compiler","pbs","stdlib","runtime-alignment","abi","syscall","frame-composer","sprites"],"agendas":[],"decisions":[],"plans":[],"lessons":[{"id":"LSN-0041","file":"discussion/lessons/DSC-0029-studio-frame-composer-syscall-and-sprite-alignment/LSN-0041-composer-must-own-public-sprite-composition.md","status":"done","created_at":"2026-04-18","updated_at":"2026-04-18"}]} +{"type":"discussion","id":"DSC-0028","status":"done","ticket":"studio-tiled-parser-assets-scene-asset-type","title":"Tiled Parser and Scene Asset-Type Ownership in Assets Workspace","created_at":"2026-04-15","updated_at":"2026-04-23","tags":["studio","assets","scene","tiled","parser","asset-type"],"agendas":[],"decisions":[],"plans":[],"lessons":[{"id":"LSN-0045","file":"discussion/lessons/DSC-0028-studio-tiled-parser-assets-scene-asset-type/LSN-0045-asset-owned-scene-bank-and-tiled-xml-workflow.md","status":"done","created_at":"2026-04-23","updated_at":"2026-04-23"}]} +{"type":"discussion","id":"DSC-0027","status":"abandoned","ticket":"studio-scene-workspace","title":"Scene Workspace for SCENE Authoring","created_at":"2026-04-14","updated_at":"2026-04-15","tags":["studio","workspace","scene","tilemap","asset","runtime-alignment"],"agendas":[{"id":"AGD-0029","file":"AGD-0029-studio-scene-workspace.md","status":"abandoned","created_at":"2026-04-14","updated_at":"2026-04-15","_override_reason":"Explicit user request on 2026-04-15 to abandon the accepted agenda and its downstream work."}],"decisions":[{"id":"DEC-0026","file":"DEC-0026-studio-scene-workspace.md","status":"abandoned","created_at":"2026-04-14","updated_at":"2026-04-15","ref_agenda":"AGD-0029","_override_reason":"Explicit user request on 2026-04-15 to abandon the accepted decision and stop using it as normative guidance."}],"plans":[{"id":"PLN-0049","file":"PLN-0049-scene-workspace-spec-and-boundary-propagation.md","status":"abandoned","created_at":"2026-04-14","updated_at":"2026-04-15","ref_decisions":["DEC-0026"],"_override_reason":"Explicit user request on 2026-04-15 to abandon all plans derived from DEC-0026."},{"id":"PLN-0050","file":"PLN-0050-scene-workspace-shell-and-project-state-foundations.md","status":"abandoned","created_at":"2026-04-14","updated_at":"2026-04-15","ref_decisions":["DEC-0026"],"_override_reason":"Explicit user request on 2026-04-15 to abandon all plans derived from DEC-0026."},{"id":"PLN-0051","file":"PLN-0051-scene-artifact-and-assets-handoff-contract.md","status":"abandoned","created_at":"2026-04-14","updated_at":"2026-04-15","ref_decisions":["DEC-0026"],"_override_reason":"Explicit user request on 2026-04-15 to abandon all plans derived from DEC-0026."},{"id":"PLN-0052","file":"PLN-0052-scene-workspace-wave-1-tilemap-editor.md","status":"abandoned","created_at":"2026-04-14","updated_at":"2026-04-15","ref_decisions":["DEC-0026"],"_override_reason":"Explicit user request on 2026-04-15 to abandon all plans derived from DEC-0026."}],"lessons":[]} +{"type":"discussion","id":"DSC-0026","status":"done","ticket":"glyph-bank-naming-alignment-with-runtime","title":"Glyph Bank Naming Alignment with Runtime DEC-0006","created_at":"2026-04-10","updated_at":"2026-04-10","tags":["packer","studio","naming","asset-contract","runtime-alignment","glyph-bank"],"agendas":[],"decisions":[],"plans":[],"lessons":[{"id":"LSN-0040","file":"discussion/lessons/DSC-0026-glyph-bank-naming-alignment-with-runtime/LSN-0040-glyph-bank-artifact-naming-alignment.md","status":"done","created_at":"2026-04-10","updated_at":"2026-04-10"}]} +{"type":"discussion","id":"DSC-0025","status":"done","ticket":"packer-pipeline-metadata-ownership","title":"Pipeline Metadata Ownership and Runtime Contract","created_at":"2026-04-09","updated_at":"2026-04-10","tags":["packer","metadata","runtime-contract","tooling","studio"],"agendas":[],"decisions":[],"plans":[],"lessons":[{"id":"LSN-0039","file":"discussion/lessons/DSC-0025-packer-pipeline-metadata-ownership/LSN-0039-runtime-header-boundary-and-tooling-owned-pipeline-metadata.md","status":"done","created_at":"2026-04-10","updated_at":"2026-04-10"}]} +{"type":"discussion","id":"DSC-0024","status":"done","ticket":"jacoco-reports-consolidation","title":"JaCoCo Reports Consolidation in Gradle","created_at":"2026-04-07","updated_at":"2026-04-07","tags":["infra","gradle","jacoco","coverage","jenkins"],"agendas":[],"decisions":[],"plans":[],"lessons":[{"id":"LSN-0038","file":"discussion/lessons/DSC-0024-jacoco-reports-consolidation/LSN-0038-jacoco-reports-consolidation.md","status":"done","created_at":"2026-04-07","updated_at":"2026-04-07"},{"id":"LSN-0044","file":"discussion/lessons/DSC-0024-jacoco-reports-consolidation/LSN-0044-jenkins-jacoco-alignment.md","status":"done","created_at":"2026-04-07","updated_at":"2026-04-07"}]} +{"type":"discussion","id":"DSC-0001","status":"done","ticket":"studio-docs-import","title":"Import docs/studio into discussion-framework artifacts","created_at":"2026-03-26","updated_at":"2026-03-26","tags":["studio","migration","discussion-framework","docs-import"],"agendas":[],"decisions":[],"plans":[],"lessons":[{"id":"LSN-0001","file":"discussion/lessons/DSC-0001-studio-docs-import/LSN-0001-assets-workspace-execution-wave-legacy.md","status":"done","created_at":"2026-03-26","updated_at":"2026-03-26"},{"id":"LSN-0002","file":"discussion/lessons/DSC-0001-studio-docs-import/LSN-0002-bank-composition-editor-legacy.md","status":"done","created_at":"2026-03-26","updated_at":"2026-03-26"},{"id":"LSN-0003","file":"discussion/lessons/DSC-0001-studio-docs-import/LSN-0003-mental-model-asset-mutations-legacy.md","status":"done","created_at":"2026-03-26","updated_at":"2026-03-26"},{"id":"LSN-0004","file":"discussion/lessons/DSC-0001-studio-docs-import/LSN-0004-mental-model-assets-workspace-legacy.md","status":"done","created_at":"2026-03-26","updated_at":"2026-03-26"},{"id":"LSN-0005","file":"discussion/lessons/DSC-0001-studio-docs-import/LSN-0005-mental-model-studio-events-and-components-legacy.md","status":"done","created_at":"2026-03-26","updated_at":"2026-03-26"},{"id":"LSN-0006","file":"discussion/lessons/DSC-0001-studio-docs-import/LSN-0006-mental-model-studio-shell-legacy.md","status":"done","created_at":"2026-03-26","updated_at":"2026-03-26"},{"id":"LSN-0007","file":"discussion/lessons/DSC-0001-studio-docs-import/LSN-0007-pack-wizard-shell-legacy.md","status":"done","created_at":"2026-03-26","updated_at":"2026-03-26"},{"id":"LSN-0008","file":"discussion/lessons/DSC-0001-studio-docs-import/LSN-0008-project-scoped-state-and-activity-legacy.md","status":"done","created_at":"2026-03-26","updated_at":"2026-03-26"},{"id":"LSN-0016","file":"discussion/lessons/DSC-0001-studio-docs-import/LSN-0016-studio-docs-import-pattern.md","status":"done","created_at":"2026-03-26","updated_at":"2026-03-26"}]} +{"type":"discussion","id":"DSC-0002","status":"done","ticket":"palette-management-in-studio","title":"Palette Management in Studio","created_at":"2026-03-26","updated_at":"2026-04-23","tags":["studio","legacy-import","palette-management","tile-bank","packer-boundary"],"agendas":[],"decisions":[],"plans":[],"lessons":[{"id":"LSN-0042","file":"discussion/lessons/DSC-0002-palette-management-in-studio/LSN-0042-schema-driven-palette-authoring-and-local-metadata-events.md","status":"done","created_at":"2026-04-23","updated_at":"2026-04-23"}]} +{"type":"discussion","id":"DSC-0003","status":"done","ticket":"packer-docs-import","title":"Import docs/packer into discussion-framework artifacts","created_at":"2026-03-26","updated_at":"2026-03-26","tags":["packer","migration","discussion-framework","docs-import"],"agendas":[],"decisions":[],"plans":[],"lessons":[{"id":"LSN-0009","file":"discussion/lessons/DSC-0003-packer-docs-import/LSN-0009-mental-model-packer-legacy.md","status":"done","created_at":"2026-03-26","updated_at":"2026-03-26"},{"id":"LSN-0010","file":"discussion/lessons/DSC-0003-packer-docs-import/LSN-0010-asset-identity-and-runtime-contract-legacy.md","status":"done","created_at":"2026-03-26","updated_at":"2026-03-26"},{"id":"LSN-0011","file":"discussion/lessons/DSC-0003-packer-docs-import/LSN-0011-foundations-workspace-runtime-and-build-legacy.md","status":"done","created_at":"2026-03-26","updated_at":"2026-03-26"},{"id":"LSN-0012","file":"discussion/lessons/DSC-0003-packer-docs-import/LSN-0012-runtime-ownership-and-studio-boundary-legacy.md","status":"done","created_at":"2026-03-26","updated_at":"2026-03-26"},{"id":"LSN-0013","file":"discussion/lessons/DSC-0003-packer-docs-import/LSN-0013-metadata-convergence-and-runtime-sink-legacy.md","status":"done","created_at":"2026-03-26","updated_at":"2026-03-26"},{"id":"LSN-0014","file":"discussion/lessons/DSC-0003-packer-docs-import/LSN-0014-pack-wizard-summary-validation-and-pack-execution-legacy.md","status":"done","created_at":"2026-03-26","updated_at":"2026-03-26"},{"id":"LSN-0015","file":"discussion/lessons/DSC-0003-packer-docs-import/LSN-0015-tile-bank-packing-contract-legacy.md","status":"done","created_at":"2026-03-26","updated_at":"2026-03-26"},{"id":"LSN-0017","file":"discussion/lessons/DSC-0003-packer-docs-import/LSN-0017-packer-docs-import-pattern.md","status":"done","created_at":"2026-03-26","updated_at":"2026-03-26"}]} +{"type":"discussion","id":"DSC-0004","status":"abandoned","ticket":"tilemap-and-metatile-runtime-binary-layout","title":"Tilemap and Metatile Runtime Binary Layout","created_at":"2026-03-26","updated_at":"2026-04-24","tags":["packer","legacy-import","tilemap","metatile","runtime-layout"],"agendas":[{"id":"AGD-0004","file":"AGD-0004-tilemap-and-metatile-runtime-binary-layout.md","status":"abandoned","created_at":"2026-03-26","updated_at":"2026-04-24","_override_reason":"Explicit user request on 2026-04-24 to abandon AGD-0004 because the agenda is no longer valid."}],"decisions":[],"plans":[],"lessons":[]} +{"type":"discussion","id":"DSC-0005","status":"open","ticket":"variable-tile-bank-palette-serialization","title":"Variable Tile Bank Palette Serialization","created_at":"2026-03-26","updated_at":"2026-03-26","tags":["packer","legacy-import","tile-bank","palette-serialization","versioning"],"agendas":[{"id":"AGD-0005","file":"AGD-0005-variable-tile-bank-palette-serialization.md","status":"open","created_at":"2026-03-26","updated_at":"2026-03-26"}],"decisions":[],"plans":[],"lessons":[]} +{"type":"discussion","id":"DSC-0006","status":"done","ticket":"pbs-game-facing-asset-refs-and-call-result-discard","title":"PBS Game-Facing Asset References and Ignored Call Result Lowering","created_at":"2026-03-27","updated_at":"2026-03-30","tags":["compiler","pbs","ergonomics","lowering","runtime","asset-identity","expression-statements"],"agendas":[],"decisions":[],"plans":[],"lessons":[{"id":"LSN-0024","file":"discussion/lessons/DSC-0006-pbs-game-facing-asset-refs-and-call-result-discard/LSN-0024-addressable-surface-host-metadata-and-ignored-value-discipline.md","status":"done","created_at":"2026-03-30","updated_at":"2026-03-30"}]} +{"type":"discussion","id":"DSC-0007","status":"done","ticket":"pbs-learn-to-discussion-lessons-migration","title":"Migrate PBS Learn Documents into Discussion Lessons","created_at":"2026-03-27","updated_at":"2026-03-27","tags":["compiler","pbs","migration","discussion-framework","lessons","learn-prune"],"agendas":[],"decisions":[],"plans":[],"lessons":[{"id":"LSN-0018","file":"discussion/lessons/DSC-0007-pbs-learn-to-discussion-lessons-migration/LSN-0018-pbs-ast-and-parser-contract-legacy.md","status":"done","created_at":"2026-03-27","updated_at":"2026-03-27"},{"id":"LSN-0019","file":"discussion/lessons/DSC-0007-pbs-learn-to-discussion-lessons-migration/LSN-0019-pbs-name-resolution-and-linking-legacy.md","status":"done","created_at":"2026-03-27","updated_at":"2026-03-27"},{"id":"LSN-0020","file":"discussion/lessons/DSC-0007-pbs-learn-to-discussion-lessons-migration/LSN-0020-pbs-runtime-values-identity-memory-boundaries-legacy.md","status":"done","created_at":"2026-03-27","updated_at":"2026-03-27"},{"id":"LSN-0021","file":"discussion/lessons/DSC-0007-pbs-learn-to-discussion-lessons-migration/LSN-0021-pbs-diagnostics-and-conformance-governance-legacy.md","status":"done","created_at":"2026-03-27","updated_at":"2026-03-27"},{"id":"LSN-0022","file":"discussion/lessons/DSC-0007-pbs-learn-to-discussion-lessons-migration/LSN-0022-pbs-globals-lifecycle-and-published-entrypoint-legacy.md","status":"done","created_at":"2026-03-27","updated_at":"2026-03-27"}]} +{"type":"discussion","id":"DSC-0008","status":"done","ticket":"pbs-low-level-asset-manager-surface","title":"PBS Low-Level Asset Manager Surface for Runtime AssetManager","created_at":"2026-03-27","updated_at":"2026-03-27","tags":["compiler","pbs","runtime","asset-manager","host-abi","stdlib","asset"],"agendas":[],"decisions":[],"plans":[],"lessons":[{"id":"LSN-0023","file":"discussion/lessons/DSC-0008-pbs-low-level-asset-manager-surface/LSN-0023-lowassets-runtime-aligned-sdk-surface.md","status":"done","created_at":"2026-03-27","updated_at":"2026-03-27"}]} +{"type":"discussion","id":"DSC-0009","status":"done","ticket":"studio-debugger-workspace-integration","title":"Integrate ../debugger into Studio as a dedicated workspace","created_at":"2026-03-30","updated_at":"2026-04-07","tags":["studio","debugger","workspace","integration","shell"],"agendas":[],"decisions":[],"plans":[],"lessons":[]} +{"type":"discussion","id":"DSC-0010","status":"done","ticket":"studio-code-editor-workspace-foundations","title":"Establish Code Editor workspace foundations in Studio without LSP","created_at":"2026-03-30","updated_at":"2026-03-31","tags":["studio","editor","workspace","multi-frontend","lsp-deferred"],"agendas":[],"decisions":[],"plans":[],"lessons":[{"id":"LSN-0026","file":"discussion/lessons/DSC-0010-studio-code-editor-workspace-foundations/LSN-0026-read-only-editor-foundations-and-semantic-deferral.md","status":"done","created_at":"2026-03-31","updated_at":"2026-03-31"}]} +{"type":"discussion","id":"DSC-0011","status":"done","ticket":"compiler-analyze-compile-build-pipeline-split","title":"Split compiler pipeline into analyze, compile, and build entrypoints","created_at":"2026-03-30","updated_at":"2026-03-30","tags":["compiler","pipeline","artifacts","build","analysis"],"agendas":[],"decisions":[],"plans":[],"lessons":[{"id":"LSN-0025","file":"discussion/lessons/DSC-0011-compiler-analyze-compile-build-pipeline-split/LSN-0025-compiler-pipeline-entrypoints-and-result-boundaries.md","status":"done","created_at":"2026-03-30","updated_at":"2026-03-30"}]} +{"type":"discussion","id":"DSC-0012","status":"done","ticket":"studio-editor-document-vfs-boundary","title":"Definir um boundary de VFS documental para tree/view/open files no Code Editor do Studio","created_at":"2026-03-31","updated_at":"2026-03-31","tags":["studio","editor","workspace","vfs","filesystem","boundary"],"agendas":[],"decisions":[],"plans":[],"lessons":[{"id":"LSN-0027","file":"discussion/lessons/DSC-0012-studio-editor-document-vfs-boundary/LSN-0027-project-document-vfs-and-session-owned-editor-boundary.md","status":"done","created_at":"2026-03-31","updated_at":"2026-03-31"}]} +{"type":"discussion","id":"DSC-0013","status":"done","ticket":"studio-editor-write-wave-supported-non-frontend-files","title":"Definir a wave inicial de edicao no Code Editor apenas para arquivos aceitos e nao relacionados ao FE","created_at":"2026-03-31","updated_at":"2026-04-02","tags":["studio","editor","workspace","write","read-only","vfs","frontend-boundary"],"agendas":[],"decisions":[],"plans":[],"lessons":[{"id":"LSN-0028","file":"discussion/lessons/DSC-0013-studio-editor-write-wave-supported-non-frontend-files/LSN-0028-controlled-editor-write-wave-and-read-only-frontend-semantic-phase.md","status":"done","created_at":"2026-04-02","updated_at":"2026-04-02"}]} +{"type":"discussion","id":"DSC-0014","status":"done","ticket":"studio-frontend-owned-semantic-editor-presentation","title":"Definir ownership do schema visual semantico do editor por frontend","created_at":"2026-04-02","updated_at":"2026-04-02","tags":["studio","editor","frontend","presentation","semantic-highlighting","compiler","pbs"],"agendas":[],"decisions":[],"plans":[],"lessons":[{"id":"LSN-0029","file":"discussion/lessons/DSC-0014-studio-frontend-owned-semantic-editor-presentation/LSN-0029-frontend-owned-semantic-presentation-descriptor-and-host-consumption.md","status":"done","created_at":"2026-04-02","updated_at":"2026-04-02"}]} +{"type":"discussion","id":"DSC-0015","status":"done","ticket":"pbs-service-facade-reserved-metadata","title":"SDK Service Bodies Calling Builtin/Intrinsic Proxies as Ordinary PBS Code","created_at":"2026-04-03","updated_at":"2026-04-03","tags":["compiler","pbs","sdk","stdlib","lowering","service","intrinsic","sdk-interface"],"agendas":[],"decisions":[],"plans":[],"lessons":[{"id":"LSN-0030","file":"discussion/lessons/DSC-0015-pbs-service-facade-reserved-metadata/LSN-0030-sdk-service-bodies-over-private-reserved-proxies.md","status":"done","created_at":"2026-04-03","updated_at":"2026-04-03"}]} +{"type":"discussion","id":"DSC-0016","status":"done","ticket":"studio-editor-scope-guides-and-brace-anchoring","title":"Scope Guides do Code Editor com ancoragem exata em braces e destaque do escopo ativo","created_at":"2026-04-03","updated_at":"2026-04-06","tags":["studio","editor","scope-guides","braces","semantic-read","frontend-contract"],"agendas":[],"decisions":[],"plans":[],"lessons":[{"id":"LSN-0034","file":"discussion/lessons/DSC-0016-studio-editor-scope-guides-and-brace-anchoring/LSN-0034-active-scope-gutter-and-frontend-owned-structural-anchors.md","status":"done","created_at":"2026-04-06","updated_at":"2026-04-06"}]} +{"type":"discussion","id":"DSC-0017","status":"done","ticket":"studio-editor-inline-type-hints-for-let-bindings","title":"Inline Type Hints for Let Bindings in the Studio Editor","created_at":"2026-04-03","updated_at":"2026-04-06","tags":["studio","editor","inline-hints","inlay-hints","lsp","pbs","type-inference"],"agendas":[],"decisions":[],"plans":[],"lessons":[{"id":"LSN-0035","file":"discussion/lessons/DSC-0017-studio-editor-inline-type-hints-for-let-bindings/LSN-0035-frontend-owned-inline-hints-with-decorative-inline-rendering.md","status":"done","created_at":"2026-04-06","updated_at":"2026-04-06"}]} +{"type":"discussion","id":"DSC-0018","status":"done","ticket":"studio-project-local-studio-state-under-dot-studio","title":"Persist project-local Studio state under .studio","created_at":"2026-04-04","updated_at":"2026-04-04","tags":["studio","project-session","project-state","persistence","dot-studio","shell","layout","setup"],"agendas":[],"decisions":[],"plans":[],"lessons":[{"id":"LSN-0031","file":"discussion/lessons/DSC-0018-studio-project-local-studio-state-under-dot-studio/LSN-0031-project-local-studio-state-and-lifecycle-safe-layout-restoration.md","status":"done","created_at":"2026-04-04","updated_at":"2026-04-04"}]} +{"type":"discussion","id":"DSC-0019","status":"done","ticket":"studio-project-local-setup-separate-from-main-studio-state","title":"Separate project-local setup from the main Studio state under .studio","created_at":"2026-04-04","updated_at":"2026-04-04","tags":["studio","project-session","project-state","persistence","dot-studio","setup","boundary"],"agendas":[],"decisions":[],"plans":[],"lessons":[{"id":"LSN-0032","file":"discussion/lessons/DSC-0019-studio-project-local-setup-separate-from-main-studio-state/LSN-0032-separate-project-config-from-session-restoration-state.md","status":"done","created_at":"2026-04-04","updated_at":"2026-04-04"}]} +{"type":"discussion","id":"DSC-0020","status":"done","ticket":"studio-editor-indentation-policy-and-project-setup","title":"Indentation Policy, Status-Bar Semantics, and Project-Local Editor Setup","created_at":"2026-04-04","updated_at":"2026-04-04","tags":["studio","editor","indentation","tabs","setup","dot-studio","configuration","ux"],"agendas":[],"decisions":[],"plans":[],"lessons":[{"id":"LSN-0033","file":"discussion/lessons/DSC-0020-studio-editor-indentation-policy-and-project-setup/LSN-0033-setup-owned-indentation-policy-and-project-bootstrap-defaults.md","status":"done","created_at":"2026-04-04","updated_at":"2026-04-04"}]} +{"type":"discussion","id":"DSC-0021","status":"done","ticket":"studio-frontend-editor-write-and-save-wave","title":"Enable Frontend Editing and Save in the Studio Code Editor","created_at":"2026-04-04","updated_at":"2026-04-06","tags":["studio","editor","frontend","write","save","vfs","lsp","pbs","access-policy"],"agendas":[],"decisions":[],"plans":[],"lessons":[{"id":"LSN-0036","file":"discussion/lessons/DSC-0021-studio-frontend-editor-write-and-save-wave/LSN-0036-vfs-owned-frontend-edit-and-save-wave.md","status":"done","created_at":"2026-04-06","updated_at":"2026-04-06"}]} +{"type":"discussion","id":"DSC-0022","status":"done","ticket":"studio-play-stop-cartridge-flow","title":"Wire the Studio Play/Stop button to shipper phase 1 cartridge preparation and runtime execution","created_at":"2026-04-06","updated_at":"2026-04-07","tags":["studio","play-stop","shipper","runtime","cartridge","shell"],"agendas":[],"decisions":[],"plans":[],"lessons":[{"id":"LSN-0043","file":"discussion/lessons/DSC-0022-studio-play-stop-and-debugger-integration/LSN-0043-studio-play-stop-and-debugger-integration.md","status":"done","created_at":"2026-04-07","updated_at":"2026-04-07"}]} +{"type":"discussion","id":"DSC-0023","status":"done","ticket":"gradle-version-catalog-migration","title":"Move dependency version management to Version Catalog (TOML)","created_at":"2026-04-07","updated_at":"2026-04-07","tags":["gradle","buildSrc","dependency-management","version-catalog"],"agendas":[],"decisions":[],"plans":[],"lessons":[{"id":"LSN-0037","file":"discussion/lessons/DSC-0023-gradle-version-catalog-migration/LSN-0037-gradle-version-catalog-adoption.md","status":"done","created_at":"2026-04-07","updated_at":"2026-04-07"}]} diff --git a/discussion/index.ndjson b/discussion/index.ndjson index f17e173d..b88da099 100644 --- a/discussion/index.ndjson +++ b/discussion/index.ndjson @@ -1,7 +1,7 @@ -{"type":"meta","next_id":{"DSC":35,"AGD":38,"DEC":35,"PLN":75,"LSN":47,"CLSN":1}} -{"type":"discussion","id":"DSC-0034","status":"in_progress","ticket":"frontend-semantic-host-projection-flexibility","title":"Frontend semantic vocabulary flexibility and declarative host projection","created_at":"2026-05-06","updated_at":"2026-05-06","tags":["compiler","compiler-general","frontend","semantics","vscode","host-projection","lsp"],"agendas":[{"id":"AGD-0037","file":"AGD-0037-frontend-semantic-host-projection-flexibility.md","status":"accepted","created_at":"2026-05-06","updated_at":"2026-05-06"}],"decisions":[{"id":"DEC-0034","file":"DEC-0034-frontend-semantic-host-projection-flexibility.md","status":"accepted","created_at":"2026-05-06","updated_at":"2026-05-06","ref_agenda":"AGD-0037"}],"plans":[{"id":"PLN-0072","file":"PLN-0072-frontend-semantic-host-projection-contract.md","status":"done","created_at":"2026-05-06","updated_at":"2026-05-06","ref_decisions":["DEC-0034"]},{"id":"PLN-0073","file":"PLN-0073-lsp-semantic-host-projection-transport.md","status":"done","created_at":"2026-05-06","updated_at":"2026-05-06","ref_decisions":["DEC-0034"]},{"id":"PLN-0074","file":"PLN-0074-vscode-semantic-host-projection-adapter.md","status":"done","created_at":"2026-05-06","updated_at":"2026-05-06","ref_decisions":["DEC-0034"]}],"lessons":[]} +{"type":"meta","next_id":{"DSC":35,"AGD":38,"DEC":35,"PLN":75,"LSN":49,"CLSN":1}} +{"type":"discussion","id":"DSC-0034","status":"done","ticket":"frontend-semantic-host-projection-flexibility","title":"Frontend semantic vocabulary flexibility and declarative host projection","created_at":"2026-05-06","updated_at":"2026-05-07","tags":["compiler","compiler-general","frontend","semantics","vscode","host-projection","lsp"],"agendas":[],"decisions":[],"plans":[],"lessons":[{"id":"LSN-0048","file":"discussion/lessons/DSC-0034-frontend-semantic-host-projection-flexibility/LSN-0048-frontend-owned-semantic-vocabularies-with-declarative-host-projection.md","status":"done","created_at":"2026-05-07","updated_at":"2026-05-07"}]} {"type":"discussion","id":"DSC-0033","status":"in_progress","ticket":"frontend-visual-theme-spec-and-css-retirement","title":"Frontend visual theme spec and retirement of host-consumed semantic CSS","created_at":"2026-05-06","updated_at":"2026-05-06","tags":["compiler","compiler-general","frontend","presentation","theming","studio","vscode","lsp","pbs"],"agendas":[{"id":"AGD-0036","file":"AGD-0036-frontend-visual-theme-spec-and-css-retirement.md","status":"accepted","created_at":"2026-05-06","updated_at":"2026-05-06"}],"decisions":[{"id":"DEC-0033","file":"DEC-0033-frontend-visual-theme-spec-and-css-retirement.md","status":"accepted","created_at":"2026-05-06","updated_at":"2026-05-06","ref_agenda":"AGD-0036"}],"plans":[{"id":"PLN-0068","file":"PLN-0068-frontend-visual-contract-and-pbs-migration.md","status":"open","created_at":"2026-05-06","updated_at":"2026-05-06","ref_decisions":["DEC-0033"]},{"id":"PLN-0069","file":"PLN-0069-lsp-visual-theme-transport-and-selection.md","status":"open","created_at":"2026-05-06","updated_at":"2026-05-06","ref_decisions":["DEC-0033"]},{"id":"PLN-0070","file":"PLN-0070-studio-visual-theme-adapter-and-css-retirement.md","status":"open","created_at":"2026-05-06","updated_at":"2026-05-06","ref_decisions":["DEC-0033"]},{"id":"PLN-0071","file":"PLN-0071-vscode-dynamic-theme-translation-adapter.md","status":"open","created_at":"2026-05-06","updated_at":"2026-05-06","ref_decisions":["DEC-0033"]}],"lessons":[]} -{"type":"discussion","id":"DSC-0032","status":"in_progress","ticket":"studio-new-lsp-api-and-v1-boundary","title":"Novo boundary entre lsp-api, lsp-v1 e a extensao VS Code","created_at":"2026-05-05","updated_at":"2026-05-05","tags":["studio","lsp","vscode","protocol","api","boundary"],"agendas":[{"id":"AGD-0035","file":"AGD-0035-studio-new-lsp-api-and-v1-boundary.md","status":"accepted","created_at":"2026-05-05","updated_at":"2026-05-05"}],"decisions":[{"id":"DEC-0032","file":"DEC-0032-studio-new-lsp-api-and-v1-boundary.md","status":"accepted","created_at":"2026-05-05","updated_at":"2026-05-05","ref_agenda":"AGD-0035"}],"plans":[{"id":"PLN-0065","file":"PLN-0065-lsp-boundary-and-module-scaffolding.md","status":"done","created_at":"2026-05-05","updated_at":"2026-05-05","ref_decisions":["DEC-0032"]},{"id":"PLN-0066","file":"PLN-0066-project-scoped-lsp-server-lifecycle-in-studio.md","status":"done","created_at":"2026-05-05","updated_at":"2026-05-05","ref_decisions":["DEC-0032"]},{"id":"PLN-0067","file":"PLN-0067-compiler-backed-dumb-lsp-server-baseline.md","status":"done","created_at":"2026-05-05","updated_at":"2026-05-05","ref_decisions":["DEC-0032"]}],"lessons":[]} +{"type":"discussion","id":"DSC-0032","status":"done","ticket":"studio-new-lsp-api-and-v1-boundary","title":"Novo boundary entre lsp-api, lsp-v1 e a extensao VS Code","created_at":"2026-05-05","updated_at":"2026-05-07","tags":["studio","lsp","vscode","protocol","api","boundary"],"agendas":[],"decisions":[],"plans":[],"lessons":[{"id":"LSN-0047","file":"discussion/lessons/DSC-0032-studio-new-lsp-api-and-v1-boundary/LSN-0047-project-scoped-lsp-boundary-and-protocol-containment.md","status":"done","created_at":"2026-05-07","updated_at":"2026-05-07"}]} {"type":"discussion","id":"DSC-0031","status":"in_progress","ticket":"studio-editor-workspace-cleanup","title":"Limpeza completa do Workspace Editor do Studio e remoção dos acoplamentos legados","created_at":"2026-05-05","updated_at":"2026-05-05","tags":["studio","editor","cleanup","vfs","lsp","migration"],"agendas":[{"id":"AGD-0034","file":"AGD-0034-vscode-editor-migration-feasibility.md","status":"accepted","created_at":"2026-05-05","updated_at":"2026-05-05"}],"decisions":[{"id":"DEC-0031","file":"DEC-0031-studio-editor-workspace-cleanup.md","status":"in_progress","created_at":"2026-05-05","updated_at":"2026-05-05","ref_agenda":"AGD-0034"}],"plans":[{"id":"PLN-0062","file":"PLN-0062-shell-session-and-state-cleanup-after-editor-removal.md","status":"done","created_at":"2026-05-05","updated_at":"2026-05-05","ref_decisions":["DEC-0031"]},{"id":"PLN-0063","file":"PLN-0063-legacy-lsp-and-vfs-module-removal-with-runtime-preservation.md","status":"done","created_at":"2026-05-05","updated_at":"2026-05-05","ref_decisions":["DEC-0031"]},{"id":"PLN-0064","file":"PLN-0064-normative-test-and-lesson-cleanup-for-editor-stack-removal.md","status":"done","created_at":"2026-05-05","updated_at":"2026-05-05","ref_decisions":["DEC-0031"]}],"lessons":[]} {"type":"discussion","id":"DSC-0030","status":"done","ticket":"studio-scene-pack-runtime-binary-contract","title":"Studio scene pack contract for runtime SCENE binary payload","created_at":"2026-04-24","updated_at":"2026-05-01","tags":["studio","packer","runtime","scene","asset-pack","binary-format","tiled"],"agendas":[],"decisions":[],"plans":[],"lessons":[{"id":"LSN-0046","file":"discussion/lessons/DSC-0030-studio-scene-pack-runtime-binary-contract/LSN-0046-canonical-scene-owns-editorial-truth-while-pack-stays-request-driven.md","status":"done","created_at":"2026-05-01","updated_at":"2026-05-01"}]} {"type":"discussion","id":"DSC-0029","status":"done","ticket":"studio-frame-composer-syscall-and-sprite-alignment","title":"Studio Alignment with Runtime FrameComposer Syscalls and Sprite Composition","created_at":"2026-04-18","updated_at":"2026-04-18","tags":["studio","compiler","pbs","stdlib","runtime-alignment","abi","syscall","frame-composer","sprites"],"agendas":[],"decisions":[],"plans":[],"lessons":[{"id":"LSN-0041","file":"discussion/lessons/DSC-0029-studio-frame-composer-syscall-and-sprite-alignment/LSN-0041-composer-must-own-public-sprite-composition.md","status":"done","created_at":"2026-04-18","updated_at":"2026-04-18"}]} diff --git a/discussion/lessons/DSC-0032-studio-new-lsp-api-and-v1-boundary/LSN-0047-project-scoped-lsp-boundary-and-protocol-containment.md b/discussion/lessons/DSC-0032-studio-new-lsp-api-and-v1-boundary/LSN-0047-project-scoped-lsp-boundary-and-protocol-containment.md new file mode 100644 index 00000000..a099f39a --- /dev/null +++ b/discussion/lessons/DSC-0032-studio-new-lsp-api-and-v1-boundary/LSN-0047-project-scoped-lsp-boundary-and-protocol-containment.md @@ -0,0 +1,106 @@ +--- +id: LSN-0047 +ticket: studio-new-lsp-api-and-v1-boundary +title: Project-Scoped LSP Boundary and Protocol Containment +created: 2026-05-07 +tags: [studio, lsp, vscode, protocol, api, boundary, compiler] +--- + +## Context + +After the legacy embedded editor stack was removed, Prometeu needed a new LSP baseline without repeating the old mistake of collapsing protocol, session lifecycle, host UI, and semantic ownership into one module. + +The main architectural pressure came from two facts: + +- the VS Code extension already existed as a real LSP client over TCP, +- and the compiler already existed as the canonical owner of semantic behavior. + +That meant the missing piece was not "add editor features first". The missing piece was a strict boundary that let the Studio host, the protocol adapter, and the compiler evolve without contaminating each other. + +## Key Decisions + +### Keep `lsp-api` Minimal and Internal + +**What:** +`lsp-api` became a narrow internal Studio boundary, starting with project-scoped lifecycle operations such as boot and shutdown instead of mirroring the LSP protocol. + +**Why:** +The Studio needed a reusable internal service boundary, not a second copy of the external wire protocol. + +**Trade-offs:** +The API starts intentionally small and may need explicit growth later, but that is safer than locking protocol-shaped DTOs into the internal architecture too early. + +### Contain `LSP4J` and Protocol DTOs Inside `lsp-v1` + +**What:** +`lsp-v1` became the only concrete protocol adapter and the only module allowed to depend on `LSP4J`. + +**Why:** +Protocol libraries are integration details. If they leak outward, the host architecture starts depending on the current transport and implementation framework instead of on stable domain boundaries. + +**Trade-offs:** +This forces explicit mapping layers and a little more ceremony, but it keeps protocol churn from infecting the rest of the codebase. + +### Make the Server Lifecycle Project-Scoped + +**What:** +The LSP server now belongs to project open/close lifecycle instead of global Studio process startup. + +**Why:** +Project scope is the real ownership boundary for source roots, compiler context, and editor-facing behavior. + +**Trade-offs:** +Lifecycle wiring is slightly more involved, but resource ownership becomes predictable and multi-project behavior stays sane. + +### Keep `compiler` as Semantic Owner Even in a Dumb First Wave + +**What:** +The baseline server remained intentionally simple in behavior, but its request handling already routes through compiler-facing bridge seams. + +**Why:** +A "temporary mock" becomes dangerous when it also becomes the architecture. The repository needed a structurally correct baseline before adding semantic depth. + +**Trade-offs:** +Wave 1 delivered less feature richness, but it created a safe foundation for later layering. + +## Patterns and Algorithms + +### Pattern: Internal Boundary, External Adapter + +The stable split is: + +1. `lsp-api` exposes internal lifecycle operations, +2. `lsp-v1` speaks protocol and transport, +3. `compiler` owns semantic and analysis behavior, +4. the VS Code extension remains an ordinary external LSP client. + +### Pattern: Build the Seams Before the Features + +The server can begin "dumb" in capability coverage if: + +- the lifecycle boundary is already correct, +- compiler access already flows through explicit bridge services, +- and protocol containment is already enforced. + +That sequence is safer than shipping richer features on top of a blurred module boundary. + +## Pitfalls + +- Do not let `lsp-api` grow into a shadow copy of the LSP protocol. +- Do not import `LSP4J` outside `lsp-v1`, even for convenience. +- Do not move semantic ownership into the protocol adapter just because the adapter is the caller-facing layer. +- Do not boot a global server for the entire Studio process when the actual ownership boundary is the project session. +- Do not treat a connectivity mock as an acceptable long-term module shape. + +## References + +- `DEC-0032` Boundary normativo entre lsp-api, lsp-v1 e a extensao VS Code +- `PLN-0065` LSP Boundary and Module Scaffolding +- `PLN-0066` Project-Scoped LSP Server Lifecycle in Studio +- `PLN-0067` Compiler-Backed Dumb LSP Server Baseline + +## Takeaways + +- Protocol adapters should stay narrow and concrete; internal Studio boundaries should stay protocol-agnostic. +- Project-scoped lifecycle is the correct owner for the LSP server. +- A dumb first wave is acceptable only when the architecture is already correct. diff --git a/discussion/lessons/DSC-0034-frontend-semantic-host-projection-flexibility/LSN-0048-frontend-owned-semantic-vocabularies-with-declarative-host-projection.md b/discussion/lessons/DSC-0034-frontend-semantic-host-projection-flexibility/LSN-0048-frontend-owned-semantic-vocabularies-with-declarative-host-projection.md new file mode 100644 index 00000000..ee5fcedd --- /dev/null +++ b/discussion/lessons/DSC-0034-frontend-semantic-host-projection-flexibility/LSN-0048-frontend-owned-semantic-vocabularies-with-declarative-host-projection.md @@ -0,0 +1,90 @@ +--- +id: LSN-0048 +ticket: frontend-semantic-host-projection-flexibility +title: Frontend-Owned Semantic Vocabularies with Declarative Host Projection +created: 2026-05-07 +tags: [compiler, compiler-general, frontend, semantics, vscode, host-projection, lsp] +--- + +## Context + +Prometeu had already established that frontend-owned visual themes should remain canonical. +The remaining semantic risk was subtler: VS Code prefers host-shaped token categories, and that pressure could easily turn the host taxonomy into the real source of semantic truth. + +This discussion closed that gap by making semantic ownership explicit: + +- the frontend keeps the canonical semantic vocabulary, +- host adaptation is additional metadata, +- and the adapter translates mechanically instead of inventing semantic policy. + +## Key Decisions + +### Keep Frontend Semantic Keys Canonical + +**What:** +Each frontend remains free to define and evolve its own semantic keys, and those keys stay canonical across the stack. + +**Why:** +Semantic meaning belongs to the language frontend, not to a single host's preferred category system. + +**Trade-offs:** +Adapters must handle more varied vocabularies, but that is the correct cost of preserving frontend ownership. + +### Add Declarative Host Projection Instead of Global Normalization + +**What:** +The frontend now authors host projection metadata describing how canonical semantic keys should map into VS Code token types, modifiers, and fallbacks. + +**Why:** +Hosts still need a practical adaptation path, but that adaptation should be explicit projection data rather than a hidden normalization rule. + +**Trade-offs:** +The contract grows an extra layer, but it stays declarative and prevents semantic meaning from being reauthored inside the adapter. + +### Keep LSP and the Extension Mechanical + +**What:** +LSP transports canonical keys plus projection metadata, and the VS Code extension consumes both mechanically. + +**Why:** +If either layer starts hand-mapping semantic meaning, the host stack becomes the de facto author of language semantics. + +**Trade-offs:** +The transport and adapter need clearer model shapes, but their responsibilities stay cleaner and more reusable. + +## Patterns and Algorithms + +### Pattern: Canonical Vocabulary Plus Per-Host Projection + +The stable flow is: + +1. frontend defines semantic keys, +2. frontend defines host projections for those keys, +3. LSP transports canonical keys and projection data together, +4. the host adapter applies the projection without reinterpretation. + +### Pattern: Mechanical Translation with Explicit Fallbacks + +Projection metadata should say not only the preferred host token type, but also the fallback when the host cannot represent the frontend key exactly. +That keeps fallback behavior visible and reviewable instead of implicit in adapter code. + +## Pitfalls + +- Do not collapse frontend semantic keys into a repository-wide host taxonomy. +- Do not hide semantic policy inside the VS Code extension just because the platform has its own token vocabulary. +- Do not transport only host-shaped token types and discard canonical frontend identity. +- Do not confuse projection metadata with the canonical semantic contract itself. + +## References + +- `DEC-0034` Frontend semantic vocabularies remain canonical and hosts consume declarative projections +- `PLN-0072` Frontend Semantic Host Projection Contract +- `PLN-0073` LSP Semantic Host Projection Transport +- `PLN-0074` VS Code Semantic Host Projection Adapter +- `DEC-0033` Frontend-owned visual theme spec as canonical presentation contract + +## Takeaways + +- Semantic ownership stays with the frontend even when the host prefers a different taxonomy. +- Host projection is the right adaptation mechanism; global normalization is not. +- LSP and host adapters stay healthier when they translate declaratively instead of authoring semantic meaning. diff --git a/discussion/workflow/agendas/AGD-0035-studio-new-lsp-api-and-v1-boundary.md b/discussion/workflow/agendas/AGD-0035-studio-new-lsp-api-and-v1-boundary.md deleted file mode 100644 index cc778e48..00000000 --- a/discussion/workflow/agendas/AGD-0035-studio-new-lsp-api-and-v1-boundary.md +++ /dev/null @@ -1,128 +0,0 @@ ---- -id: AGD-0035 -ticket: studio-new-lsp-api-and-v1-boundary -title: Novo boundary entre lsp-api, lsp-v1 e a extensao VS Code -status: accepted -created: 2026-05-05 -resolved: 2026-05-05 -decision: DEC-0032 -tags: [studio, lsp, vscode, protocol, api, boundary] ---- - -## Pain - -O stack legado de editor, `prometeu-lsp` e `prometeu-vfs` acabou de ser removido. O próximo passo natural é reconstruir o backend de linguagem, mas sem repetir o erro anterior de misturar engine semântica, transporte LSP, sessão editorial e host UI em um único desenho. - -Ao mesmo tempo, já existe uma extensão em `tools/vscode-extension` que hoje sabe conectar via TCP em `127.0.0.1:7777` e falar LSP como cliente real. Isso reduz incerteza no lado do FE, mas aumenta a exigência arquitetural do backend: o servidor novo precisa nascer com boundary correto. - -O risco central é reintroduzir acoplamento acidental entre: - -- contratos internos de linguagem; -- transporte externo LSP; -- implementação concreta baseada em `LSP4J`; -- e necessidades específicas do VS Code. - -## Context - -- O cleanup do stack legado foi fechado por `DEC-0031`. -- A extensão VS Code já existe em `tools/vscode-extension`. -- A extensão usa `vscode-languageclient` e conecta por socket TCP configurável. -- O usuário quer explicitamente que `LSP4J` **não vaze** de `lsp-v1`. -- A intenção geral do produto é que o Studio fale a própria língua internamente e exponha adapters externos para FEs, no mesmo espírito já discutido para integrações como Tiled. - -Hoje, a pergunta não é "como implementar o LSP inteiro", mas sim: - -- que módulos recriar; -- qual boundary o `lsp-api` realmente deve carregar; -- e qual responsabilidade cabe a `lsp-v1` como adapter concreto. - -Também já existe um direcionamento adicional do produto: - -- `lsp-v1` deve consumir serviços existentes de `compiler`; -- `lsp-api` deve expor funcionalidades reutilizáveis por outras partes do sistema; -- o bootstrap do servidor deve acontecer quando um projeto é aberto, e o shutdown quando o projeto é fechado; -- a API pode começar mínima, por exemplo com `boot server` e `shutdown server`, e crescer só quando houver necessidade real. - -## Open Questions - -- [x] O `lsp-api` deve expor contratos próprios de domínio/serviço ou DTOs alinhados diretamente ao protocolo LSP? - R: o lsp-api deve expor somente servicos que serao usados por outras partes do sistema, e nao ser um espelho do protocolo. -- [x] O `lsp-v1` deve ser somente um adapter `LSP4J` sobre serviços internos de `compiler`, ou também pode carregar parte da orquestração de sessão? - R: O lsp-v1 deve conter o servidor e todo o necessario para falar LSP, incluindo DTOs e dependencias de LSP4J (e fazer uso de compiler quando necessario). o start e o stop do servidor podem ser chamados via lsp-api, mas a logica de orquestracao de sessao deve ficar dentro do lsp-v1. -- [x] O lifecycle de bootstrap/shutdown do servidor por projeto pertence ao `lsp-api`, ao `lsp-v1`, ou a outro serviço do Studio? - R: o contrato fica no lsp-api, mas a logica de orquestracao fica no lsp-v1. o lsp-api pode expor um contrato como `bootServer(project)` e `shutdownServer(project)`, mas a implementacao concreta e a logica de associar o servidor ao projeto fica no lsp-v1. -- [x] O canal de automação (`compile/build/run/debug`) deve viver fora do novo `lsp-api` desde o início? - R: o canal de automacao deve viver fora do lsp-api. nesse primeiro momento o foco principal deve ser o LSP e o comportamento editorial/semantico. o canal de automacao pode ser discutido e implementado separadamente, sem misturar responsabilidades. -- [x] O `tools/vscode-extension` deve continuar falando LSP puro em socket TCP, ou o produto precisa reservar outra estratégia de transporte já nesta fase? - R: o vscode-extension deve continuar falando LSP puro em socket TCP. o lsp-api deve ser agnóstico ao transporte, mas ainda aceito recomendacoes q sejam mais faceis ou performaticas. - -## Options - -### Option A - `lsp-api` como API diretamente moldada pelo protocolo LSP -- **Approach:** recriar `lsp-api` com tipos e serviços muito próximos da superfície do protocolo, deixando `lsp-v1` apenas como bootstrap `LSP4J` e roteamento para `compiler`. -- **Pro:** acelera integração com o cliente existente e reduz tradução entre camadas. -- **Con:** tende a tornar o protocolo externo dono do desenho interno; muda mal quando surgir outro FE ou outro adapter. -- **Maintainability:** fraca. O risco de vazamento conceitual do protocolo para dentro do domínio é alto, mesmo sem importar classes `LSP4J` fora de `lsp-v1`. - -### Option B - `lsp-api` mínima e operacional; `lsp-v1` como adapter LSP4J que consome `compiler` -- **Approach:** `lsp-api` expõe uma surface mínima e reutilizável para o sistema, começando com operações como `boot server(project)` e `shutdown server(project)` e, no máximo, contratos estáveis que outras partes do Studio precisem enxergar. `lsp-v1` concentra a implementação concreta do servidor, depende exclusivamente de `LSP4J`, e consome os serviços do `compiler` para responder às capacidades LSP. -- **Pro:** respeita a regra de não vazamento de `LSP4J`, evita inflar a API cedo demais e alinha o lifecycle do servidor ao projeto aberto, não ao processo global do Studio. -- **Con:** exige disciplina para não transformar `lsp-api` em um espelho parcial do protocolo nem `lsp-v1` em um segundo backend semântico solto do `compiler`. -- **Maintainability:** forte. O backend nasce hexagonal e o custo de evolução fica mais previsível. - -### Option C - Sem `lsp-api`; expor apenas um servidor LSP concreto em `lsp-v1` -- **Approach:** pular a separação e concentrar tudo em um único módulo novo de servidor, com contratos locais apenas package-private ou internos. -- **Pro:** menor custo inicial de scaffolding. -- **Con:** repete exatamente o tipo de colapso arquitetural que gerou o legado descartado; dificulta teste, substituição de transporte e integração com outros FEs. -- **Maintainability:** ruim. A velocidade inicial é comprada com dívida estrutural imediata. - -## Discussion - -O dado novo mais importante é que o cliente VS Code já está funcional como cliente LSP puro. Isso elimina a necessidade de desenhar o protocolo "pensando no editor". O editor já sabe falar LSP; quem precisa de disciplina agora é o Studio. - -Isso empurra a arquitetura para uma separação bem objetiva: - -- `lsp-api` não deve ser "API pública do protocolo"; -- `lsp-api` deve ser uma API interna e mínima do backend de linguagem do Studio; -- `lsp-v1` deve ser o adapter LSP concreto e consumidor dos serviços de `compiler`; -- `LSP4J` deve existir exclusivamente em `lsp-v1`. - -O ponto sensível é não confundir "API interna" com "engine concreta". Se `lsp-api` virar um lugar para pôr qualquer detalhe de sessão, thread, socket, `CompletableFuture` de transporte, ou estruturas do `LSP4J`, ele já nasce errado. Pelo direcionamento atual, a API deve começar deliberadamente estreita: - -- boot do servidor por projeto; -- shutdown do servidor por projeto; -- e só depois crescer quando outro consumidor real do sistema exigir isso. - -Também vale separar desde já o que não pertence ao LSP: - -- `compile/build/run/debug` não devem entrar no `lsp-api` por conveniência; -- esses fluxos pertencem a um contrato de automação paralelo; -- o LSP deve se limitar ao que é comportamento editorial/semântico. - -Outro ponto: o usuário já fixou que o Studio é o backend autoritativo e o cliente externo é só cliente. Isso reforça que o lifecycle do servidor precisa acompanhar o projeto aberto. Em outras palavras: - -- abrir Studio não implica subir servidor LSP global; -- abrir projeto pode implicar subir o servidor LSP daquele projeto; -- fechar projeto deve encerrar o servidor correspondente. - -As respostas atuais também fecharam um boundary operacional importante: - -- quem "fala LSP" de verdade é o `lsp-v1`; -- `lsp-api` não é adapter nem espelho do protocolo; -- `lsp-api` existe para expor um boundary interno consumível pelo Studio; -- o contrato mínimo inicial pode ser pequeno, desde que suficiente para boot/shutdown por projeto; -- DTOs, tipos e dependências do protocolo podem existir em `lsp-v1` sem contaminar a API interna. - -## Resolution - -Direção recomendada para convergir: - -1. recriar `lsp-api` como surface interna mínima e reutilizável do sistema, começando com bootstrap e shutdown por projeto; -2. recriar `lsp-v1` como adapter LSP/JSON-RPC concreto, com dependência exclusiva de `LSP4J`; -3. fazer `lsp-v1` consumir serviços existentes de `compiler`, em vez de reconstruir pipeline semântico próprio; -4. deixar a lógica concreta de orquestração de sessão e associação `projeto -> servidor` dentro de `lsp-v1`, mesmo quando o bootstrap/shutdown for disparado através de `lsp-api`; -5. tratar qualquer tipo `LSP4J` fora de `lsp-v1` como violação arquitetural; -6. manter `tools/vscode-extension` como cliente LSP puro em socket TCP; -7. discutir separadamente o contrato de automação para `compile/build/run/debug`, em vez de empurrá-lo para dentro do LSP. - -Neste ponto, a agenda já tem direção clara o bastante para virar `decision`. O que ainda resta fechar depois disso é implementação, não escolha arquitetural principal. diff --git a/discussion/workflow/agendas/AGD-0037-frontend-semantic-host-projection-flexibility.md b/discussion/workflow/agendas/AGD-0037-frontend-semantic-host-projection-flexibility.md deleted file mode 100644 index 59216d56..00000000 --- a/discussion/workflow/agendas/AGD-0037-frontend-semantic-host-projection-flexibility.md +++ /dev/null @@ -1,85 +0,0 @@ ---- -id: AGD-0037 -ticket: frontend-semantic-host-projection-flexibility -title: Frontend Semantic Vocabulary Flexibility and Host Projection -status: accepted -created: 2026-05-06 -resolved: 2026-05-06 -decision: DEC-0034 -tags: [compiler, compiler-general, frontend, semantics, vscode, host-projection, lsp] ---- - -## Pain - -The current discussion exposed an architectural tension: - -- frontend semantic keys must remain frontend-owned and flexible, -- but VS Code prefers host-shaped semantic token categories and modifiers, -- and forcing frontend vocabularies into a rigid global taxonomy would collapse frontend ownership into host constraints. - -If Prometeu treats VS Code semantic categories as the canonical semantic contract, the frontend loses semantic freedom and the wrong layer starts owning language meaning. - -## Context - -Domain owner: `compiler/general` - -This discussion extends `DEC-0033` rather than replacing it. -`DEC-0033` already locked that visual themes are frontend-owned and hosts are adapters. - -What remained implicit was how a frontend-owned semantic vocabulary should adapt to host capabilities when the host prefers a different semantic model. - -The key clarification is: - -- the frontend semantic vocabulary remains canonical, -- host adaptation is declarative projection, -- host projection does not become the canonical semantic contract. - -## Open Questions - -- [x] Should Prometeu define a rigid global semantic token taxonomy shared by every frontend? - R: no. Each frontend keeps its own vocabulary. -- [x] How should VS Code consume flexible frontend vocabularies without becoming the owner of semantic meaning? - R: through a frontend-authored host projection for VS Code. -- [x] Does this revise `DEC-0033`? - R: it complements `DEC-0033` by clarifying semantic vocabulary and host projection responsibilities. - -## Options - -### Option A - Canonicalize around VS Code token types - -- **Approach:** Force frontends to express semantic meaning in a shared VS Code-shaped taxonomy. -- **Pro:** Simplifies host adaptation. -- **Con:** Makes the host model canonical and removes frontend semantic freedom. -- **Maintainability:** Poor. It solves adapter simplicity by weakening frontend ownership. - -### Option B - Keep frontend vocabularies canonical and add declarative host projection - -- **Approach:** Let each frontend define its own semantic keys and publish host projection metadata that explains how a host such as VS Code should adapt those keys. -- **Pro:** Preserves frontend semantic ownership while keeping host adaptation mechanical. -- **Con:** Requires an additional contract layer. -- **Maintainability:** Strong. Ownership stays correct and adapters remain declarative. - -## Tradeoffs - -Option A would make the current VS Code situation easier, but only by moving semantic authorship to the wrong layer. - -Option B adds contract surface, but that surface is the correct one because it keeps the frontend canonical and makes host projection explicit rather than implicit. - -## Recommendation - -Adopt Option B. - -Frontend semantic keys remain canonical and flexible. -Hosts such as VS Code consume a declarative projection authored by the frontend for that host. - -## Discussion - -This discussion is intentionally narrow. -It does not reopen the frontend-owned visual theme decision. -It only clarifies that semantic vocabulary itself must also remain frontend-owned, and that host adaptation must be expressed as projection rather than normalization into a rigid shared taxonomy. - -## Resolution - -Accepted on 2026-05-06. - -Prometeu keeps frontend-owned semantic vocabularies flexible and introduces declarative host projection as the adaptation mechanism for hosts such as VS Code. diff --git a/discussion/workflow/decisions/DEC-0032-studio-new-lsp-api-and-v1-boundary.md b/discussion/workflow/decisions/DEC-0032-studio-new-lsp-api-and-v1-boundary.md deleted file mode 100644 index d3d19bcc..00000000 --- a/discussion/workflow/decisions/DEC-0032-studio-new-lsp-api-and-v1-boundary.md +++ /dev/null @@ -1,196 +0,0 @@ ---- -id: DEC-0032 -ticket: studio-new-lsp-api-and-v1-boundary -title: Boundary normativo entre lsp-api, lsp-v1 e a extensao VS Code -status: accepted -created: 2026-05-05 -accepted: 2026-05-05 -agenda: AGD-0035 -plans: [PLN-0065, PLN-0066, PLN-0067] -tags: [studio, lsp, vscode, protocol, api, boundary, compiler] ---- - -## Decision - -O repositório SHALL reconstruir o stack de linguagem do Studio com separação explícita entre: - -1. `lsp-api` como boundary interno do Studio; -2. `lsp-v1` como adapter LSP/JSON-RPC concreto; -3. `compiler` como owner dos serviços semânticos e de análise consumidos por esse adapter; -4. `tools/vscode-extension` como cliente externo que continua falando LSP puro via socket TCP. - -Esta decisão ALSO locks os seguintes pontos: - -1. `lsp-api` MUST NOT ser espelho do protocolo LSP; -2. `lsp-api` MUST expor apenas funcionalidades internas realmente consumíveis por outras partes do Studio; -3. `lsp-api` MAY começar mínima, por exemplo com contratos como `bootServer(project)` e `shutdownServer(project)`; -4. `lsp-v1` MUST concentrar o servidor LSP concreto, os DTOs de protocolo, o transporte e qualquer dependência de `LSP4J`; -5. `LSP4J` MUST NOT vazar para fora de `lsp-v1`; -6. `lsp-v1` MUST consumir serviços existentes de `compiler` em vez de reconstruir pipeline semântico próprio; -7. o lifecycle do servidor LSP MUST ser associado à abertura e ao fechamento de projeto, não à abertura global do processo Studio; -8. o atual `lsp-v1` presente hoje no repositório serve apenas como mock de conectividade VS Code ↔ Studio e MUST NOT ser tratado como padrão arquitetural, base estrutural ou referência de implementação do backend definitivo. -9. a primeira onda de implementação desta decisão SHALL priorizar arquitetura, lifecycle e separação de responsabilidades, mesmo que o comportamento LSP permaneça deliberadamente simples ou "dumb" por um período controlado. - -## Rationale - -O stack legado anterior foi removido justamente porque misturava responsabilidades erradas e criou boundaries frágeis entre UI, sessão, semântica e transporte. - -Ao mesmo tempo, o projeto já tem dois fatos importantes: - -1. a extensão VS Code já existe e já sabe atuar como cliente LSP puro; -2. o Studio já possui serviços de `compiler` que devem continuar sendo a fonte real de comportamento semântico. - -Logo, o problema não é "inventar um cliente" nem "reescrever a semântica". O problema é definir corretamente: - -1. o que é boundary interno reutilizável do Studio; -2. o que é adapter concreto de protocolo; -3. e onde termina a influência do protocolo externo. - -Essa separação reduz acoplamento, melhora teste e evita que detalhes de `LSP4J` ou do transporte contaminem o restante da base. - -Também existe uma prioridade explícita de rollout: - -1. primeiro consolidar a arquitetura; -2. depois adicionar capacidade semântica por camadas; -3. sem obrigar a primeira implementação a já ser semanticamente rica. - -Isso evita repetir o padrão anterior de crescer funcionalidade em cima de uma base estrutural errada. - -## Technical Specification - -### 1. Module Roles - -`lsp-api` MUST ser tratado como módulo de boundary interno do Studio. - -Ele SHALL: - -1. expor somente contratos que façam sentido para outros consumidores internos do sistema; -2. permanecer agnóstico ao protocolo LSP concreto; -3. permanecer agnóstico a `LSP4J`; -4. permanecer agnóstico ao transporte TCP ou a qualquer detalhe de socket; -5. começar com surface mínima suficiente para o lifecycle do servidor por projeto. - -`lsp-v1` MUST ser tratado como o primeiro adapter concreto do boundary acima. - -Ele SHALL: - -1. implementar o servidor LSP; -2. carregar os DTOs e tipos de protocolo que forem necessários para falar LSP; -3. carregar a dependência de `LSP4J`; -4. realizar a tradução entre o mundo do protocolo e os serviços internos consumidos; -5. concentrar a lógica concreta de sessão e associação `projeto -> servidor`. - -### 2. LSP4J Containment - -O repositório MUST tratar `LSP4J` como dependência exclusiva de `lsp-v1`. - -Portanto: - -1. nenhum tipo de `LSP4J` MAY aparecer em `lsp-api`; -2. nenhum tipo de `LSP4J` MAY aparecer em outros módulos do Studio; -3. nenhum contrato de `lsp-api` MAY depender semanticamente de tipos, nomes ou formas obrigadas pelo `LSP4J`; -4. qualquer vazamento de `LSP4J` para fora de `lsp-v1` SHALL ser tratado como violação arquitetural. - -### 3. Compiler Ownership - -`lsp-v1` MUST consumir serviços existentes de `compiler` quando precisar responder capacidades editoriais e semânticas. - -Isso implica: - -1. `lsp-v1` MUST NOT reconstruir uma engine semântica paralela por conveniência; -2. `lsp-v1` MUST preferir compor sobre entrypoints e serviços canônicos do `compiler`; -3. qualquer lacuna percebida no `compiler` para servir o novo backend SHALL ser tratada como evolução explícita do `compiler`, e não como autorização para duplicação semântica dentro de `lsp-v1`. - -### 4. Server Lifecycle - -O lifecycle do servidor MUST ser project-scoped. - -Regras: - -1. abrir o processo Studio MUST NOT implicitamente significar "subir um servidor LSP global"; -2. abrir um projeto MAY disparar `bootServer(project)` através do boundary exposto por `lsp-api`; -3. fechar um projeto MUST disparar `shutdownServer(project)` para o servidor correspondente; -4. a implementação concreta desse bootstrap/shutdown e o vínculo entre projeto e instância do servidor MUST residir em `lsp-v1`. - -### 5. Internal API Minimalism - -`lsp-api` MUST nascer pequeno. - -Ele SHALL: - -1. expor apenas o que outro consumidor interno realmente precise enxergar; -2. evitar DTOs de protocolo sem necessidade; -3. evitar antecipar capacidades futuras sem consumidor real; -4. crescer somente quando houver pressão concreta de uso interno. - -O contrato inicial mínimo aceito por esta decisão é: - -1. `bootServer(project)` -2. `shutdownServer(project)` - -Contratos adicionais MAY ser adicionados depois, mas não fazem parte do lock inicial desta decisão. - -### 6. VS Code Transport - -`tools/vscode-extension` SHALL permanecer cliente LSP puro via socket TCP nesta fase. - -Isso implica: - -1. a extensão atual pode continuar evoluindo nesse modelo; -2. `lsp-api` MUST permanecer agnóstico a esse transporte; -3. mudanças futuras de transporte MAY ser discutidas depois, mas não fazem parte do boundary normativo inicial. - -### 7. Current Mock Status - -O `lsp-v1` que existe hoje para testes de conectividade entre VS Code e Studio MUST ser tratado como mock transitório. - -Ele MUST NOT: - -1. servir de blueprint estrutural do novo servidor; -2. servir de contrato implícito do sistema; -3. servir de justificativa para manter responsabilidades colapsadas; -4. contaminar o padrão de código alvo do backend definitivo. - -O backend definitivo SHALL priorizar: - -1. separação clara de responsabilidades; -2. boundaries pequenos e explícitos; -3. código fácil de manter; -4. composição sobre serviços canônicos do `compiler`; -5. isolamento rígido do adapter de protocolo. - -### 8. Implementation Wave 1 - -A primeira onda de implementação derivada desta decisão MUST focar em transformar o mock atual em uma estrutura sólida de trabalho. - -Essa onda SHALL incluir: - -1. `lsp-api` mínimo com bootstrap e shutdown por projeto; -2. `lsp-v1` organizado como adapter concreto limpo, mesmo que ainda responda um conjunto reduzido ou simplificado de capacidades; -3. boot do servidor quando o projeto abrir; -4. shutdown do servidor quando o projeto fechar; -5. isolamento explícito entre boundary interno, adapter de protocolo e consumo de `compiler`. - -Essa onda MUST NOT ser bloqueada pela ausência de "carne semântica" completa. - -Em outras palavras: - -1. é aceitável manter um comportamento LSP inicial deliberadamente simples; -2. não é aceitável manter um padrão arquitetural improvisado só porque o comportamento ainda é simples; -3. a evolução semântica futura SHALL acontecer por camadas sobre a estrutura consolidada. - -## Constraints - -1. Esta decisão MUST preservar a separação entre boundary interno e adapter externo. -2. Esta decisão MUST preservar `compiler` como owner semântico do sistema. -3. Esta decisão MUST impedir vazamento de `LSP4J` para fora de `lsp-v1`. -4. Esta decisão MUST impedir que o mock atual de conectividade seja usado como padrão do produto. -5. Esta decisão MUST manter `compile/build/run/debug` fora do escopo do `lsp-api` nesta fase. -6. Qualquer plano derivado desta decisão MUST refletir explicitamente o lifecycle por projeto e a contenção de protocolo em `lsp-v1`. -7. O primeiro plano derivado desta decisão MUST priorizar a consolidação estrutural do servidor antes do enriquecimento semântico. - -## Revision Log - -- 2026-05-05: Initial draft from AGD-0035. -- 2026-05-05: Added explicit phase-1 rollout guidance to solidify architecture before semantic depth. -- 2026-05-05: Accepted and decomposed into PLN-0065, PLN-0066, and PLN-0067. diff --git a/discussion/workflow/decisions/DEC-0034-frontend-semantic-host-projection-flexibility.md b/discussion/workflow/decisions/DEC-0034-frontend-semantic-host-projection-flexibility.md deleted file mode 100644 index 7532a2d8..00000000 --- a/discussion/workflow/decisions/DEC-0034-frontend-semantic-host-projection-flexibility.md +++ /dev/null @@ -1,112 +0,0 @@ ---- -id: DEC-0034 -ticket: frontend-semantic-host-projection-flexibility -title: Frontend semantic vocabularies remain canonical and hosts consume declarative projections -status: accepted -created: 2026-05-06 -accepted: 2026-05-06 -agenda: AGD-0037 -plans: [PLN-0072, PLN-0073, PLN-0074] -tags: [compiler, compiler-general, frontend, semantics, vscode, host-projection, lsp] ---- - -## Decision - -Prometeu SHALL keep semantic vocabularies frontend-owned and canonical. -Hosts such as VS Code SHALL consume declarative host projection data authored by the frontend instead of forcing frontend semantic keys into a rigid shared host taxonomy. - -This decision locks the following normative points: - -1. Each frontend MUST remain free to define its own semantic keys. -2. Prometeu MUST NOT introduce a rigid global semantic token taxonomy as the canonical contract for all frontends. -3. Host-facing semantic adaptation MUST happen through frontend-authored host projection metadata. -4. Host projection metadata MUST be declarative and MUST NOT become the canonical semantic vocabulary. -5. VS Code adaptation MUST consume the frontend semantic vocabulary plus its VS Code projection, not reinterpret semantic meaning ad hoc inside the extension. - -## Rationale - -The current stack already establishes frontend ownership over visual themes. -Without this complementary rule, semantic vocabulary itself could still drift toward host ownership because VS Code prefers a different semantic model than a frontend may naturally publish. - -If the repository made VS Code token categories canonical, it would: - -1. collapse frontend semantic freedom, -2. move semantic authorship into the host layer, -3. and make frontend evolution hostage to one specific adapter model. - -Declarative host projection preserves the correct ownership boundary: - -1. frontend defines semantic meaning, -2. frontend also defines how a given host should project that meaning, -3. host adapters translate mechanically. - -## Technical Specification - -### 1. Canonical Semantic Vocabulary - -The canonical semantic vocabulary for a document language MUST live in that frontend's contract surface. - -This implies: - -1. semantic keys remain frontend-owned, -2. semantic keys MAY vary significantly between frontends, -3. semantic keys MUST NOT be rewritten into a mandatory repository-wide host-shaped taxonomy. - -### 2. Host Projection Contract - -Frontend metadata MUST evolve to support host projection descriptors. - -At minimum, a host projection descriptor for VS Code MUST be capable of expressing: - -1. which canonical semantic key is being projected, -2. which VS Code semantic token type should receive that key, -3. which VS Code semantic token modifiers, if any, should accompany that projection, -4. any fallback behavior needed when the host cannot represent the frontend key exactly. - -The host projection descriptor MAY support other hosts later, but the first required host projection is VS Code. - -### 3. Ownership Rules - -Ownership SHALL be: - -1. frontend owns semantic keys, -2. frontend owns host projection metadata, -3. LSP transports both, -4. the host adapter translates both. - -The extension MUST NOT become the place where semantic meaning is hand-mapped or reauthored as code-driven policy. - -### 4. Relationship to DEC-0033 - -This decision complements `DEC-0033`. - -`DEC-0033` remains normative for: - -1. frontend-owned visual theme contracts, -2. frontend-owned theme variants, -3. host adapter responsibilities for visual rendering. - -This decision adds the semantic vocabulary clarification that `DEC-0033` left implicit: - -1. semantic vocabularies remain frontend-owned and flexible, -2. host adaptation is projection, not normalization. - -### 5. VS Code Adapter Rule - -For VS Code specifically: - -1. the extension MUST consume frontend-owned semantic keys, -2. the extension MUST consume frontend-authored VS Code projection metadata, -3. the extension MUST apply that projection mechanically, -4. the extension MUST NOT force every frontend into a single rigid shared semantic taxonomy to satisfy VS Code. - -## Constraints - -1. No plan derived from this decision may replace frontend semantic keys with a mandatory global host taxonomy. -2. Any plan touching VS Code semantic adaptation MUST include declarative host projection support. -3. Any plan touching LSP transport for semantic vocabularies MUST preserve frontend canonical keys. -4. This decision MUST be treated as complementary to `DEC-0033`, not as a rollback of frontend-owned theming. - -## Revision Log - -- 2026-05-06: Initial accepted decision from AGD-0037. diff --git a/discussion/workflow/plans/PLN-0065-lsp-boundary-and-module-scaffolding.md b/discussion/workflow/plans/PLN-0065-lsp-boundary-and-module-scaffolding.md deleted file mode 100644 index 0783cf6c..00000000 --- a/discussion/workflow/plans/PLN-0065-lsp-boundary-and-module-scaffolding.md +++ /dev/null @@ -1,118 +0,0 @@ ---- -id: PLN-0065 -ticket: studio-new-lsp-api-and-v1-boundary -title: LSP Boundary and Module Scaffolding -status: done -created: 2026-05-05 -completed: 2026-05-05 -tags: [studio, lsp, api, boundary, modules, architecture] ---- - -## Objective - -Recreate `prometeu-lsp:prometeu-lsp-api` and `prometeu-lsp:prometeu-lsp-v1` with a structurally correct boundary that is ready for long-term maintenance, while intentionally keeping the initial server behavior minimal. - -## Background - -`DEC-0032` locks that: - -- `lsp-api` is an internal Studio boundary, not a mirror of the LSP protocol; -- `lsp-v1` is the concrete LSP adapter and the only module allowed to depend on `LSP4J`; -- the current mock server shape MUST NOT be treated as the product pattern; -- wave 1 prioritizes architecture and lifecycle over semantic depth. - -The repository already reserves `prometeu-lsp:*` in `settings.gradle.kts`, but the modules are currently empty shells after the cleanup. - -## Scope - -### Included -- Recreate Gradle/module structure for `prometeu-lsp-api` and `prometeu-lsp-v1`. -- Define the minimal internal API contract for server lifecycle by project. -- Establish package boundaries that keep protocol DTOs and `LSP4J` types out of `lsp-api`. -- Add boundary-oriented tests or build checks where feasible. - -### Excluded -- Wiring the server into Studio project open/close. -- Rich semantic behavior, diagnostics, definition, symbols, or incremental analysis. -- Automation channel work for `compile/build/run/debug`. - -## Non-Goals - -- Full language feature implementation. -- Any attempt to preserve compatibility with the legacy removed `prometeu-lsp`. -- Transport changes in the VS Code extension. - -## Execution Steps - -### Step 1 - Recreate the Gradle modules with explicit dependency ownership - -**What:** Reintroduce the `prometeu-lsp-api` and `prometeu-lsp-v1` modules as clean boundaries. -**How:** Restore the module directories and `build.gradle.kts` files, wire them in `settings.gradle.kts`, and keep dependencies explicit: - -- `prometeu-lsp-api` depends only on stable internal modules it truly needs; -- `prometeu-lsp-v1` depends on `prometeu-lsp-api`, `compiler` services it consumes, and `LSP4J`; -- no other Studio module depends on `LSP4J`. - -**File(s):** `settings.gradle.kts`, `prometeu-lsp/prometeu-lsp-api/build.gradle.kts`, `prometeu-lsp/prometeu-lsp-v1/build.gradle.kts`, affected root/module build files. - -### Step 2 - Define the minimal internal lifecycle contract in `lsp-api` - -**What:** Create the smallest stable API needed by the Studio host. -**How:** Add internal contracts such as a project-scoped `bootServer(project)` and `shutdownServer(project)` surface plus the minimal supporting DTO/entity types required by that lifecycle. Keep the API transport-agnostic and free of protocol DTOs. -**File(s):** `prometeu-lsp/prometeu-lsp-api/src/main/java/**`. - -### Step 3 - Define the adapter shape in `lsp-v1` - -**What:** Establish the internal code organization of the concrete adapter. -**How:** Create clear package slices inside `lsp-v1`, such as: - -- lifecycle/bootstrap, -- server host/transport, -- protocol DTO mapping, -- compiler-facing service bridge. - -The implementation may stay behaviorally dumb, but the structure MUST already reflect the final responsibility split. -**File(s):** `prometeu-lsp/prometeu-lsp-v1/src/main/java/**`. - -### Step 4 - Add boundary conformance tests - -**What:** Prevent architectural drift from day 1. -**How:** Add tests or static checks that fail if: - -- `lsp-api` imports `LSP4J`; -- protocol DTOs leak into `lsp-api`; -- non-`lsp-v1` Studio modules start importing `LSP4J`. - -**File(s):** `prometeu-lsp/prometeu-lsp-api/src/test/java/**`, `prometeu-lsp/prometeu-lsp-v1/src/test/java/**`, or build-level checks if that is cleaner. - -## Test Requirements - -### Unit Tests -- Verify the lifecycle contracts in `lsp-api` have deterministic defaults and null-safety. -- Verify `lsp-v1` module-local bootstrap pieces can be instantiated without a running Studio shell. -- Verify boundary checks catch `LSP4J` leakage. - -### Integration Tests -- Run a root or targeted Gradle build proving the new modules compile and coexist with `prometeu-studio` and `prometeu-app`. - -### Manual Verification -- Inspect the recreated module tree and confirm `lsp-api` contains no protocol or `LSP4J` types. - -## Acceptance Criteria - -- [x] `prometeu-lsp-api` and `prometeu-lsp-v1` exist again as active modules. -- [x] `lsp-api` exposes only internal lifecycle-oriented contracts. -- [x] `lsp-v1` is the only module allowed to depend on `LSP4J`. -- [x] The new module structure expresses clear responsibility boundaries even with dumb behavior. -- [x] Boundary conformance is covered by tests or equivalent build checks. - -## Dependencies - -- `DEC-0032` accepted and normatively locked. -- Current Gradle graph and module includes available for reactivation. - -## Risks - -- Reintroducing the modules too loosely can recreate the same ambiguity that killed the legacy stack. -- An underspecified API can force churn later; an oversized API can lock the wrong shape too early. -- Build-only enforcement may miss architectural drift unless the checks are explicit. diff --git a/discussion/workflow/plans/PLN-0066-project-scoped-lsp-server-lifecycle-in-studio.md b/discussion/workflow/plans/PLN-0066-project-scoped-lsp-server-lifecycle-in-studio.md deleted file mode 100644 index 14fa4f60..00000000 --- a/discussion/workflow/plans/PLN-0066-project-scoped-lsp-server-lifecycle-in-studio.md +++ /dev/null @@ -1,103 +0,0 @@ ---- -id: PLN-0066 -ticket: studio-new-lsp-api-and-v1-boundary -title: Project-Scoped LSP Server Lifecycle in Studio -status: done -created: 2026-05-05 -completed: 2026-05-05 -tags: [studio, lsp, lifecycle, projects, boot, shutdown] ---- - -## Objective - -Wire the new LSP server lifecycle into the Studio project lifecycle so a server starts when a project opens and stops when that project closes, without introducing a process-global LSP service. - -## Background - -`DEC-0032` requires a project-scoped server lifecycle and explicitly rejects a global Studio-wide server. The current natural integration points are: - -- `StudioProjectSession` -- `StudioProjectSessionFactory` -- `StudioWindowCoordinator` - -These surfaces already own project startup and teardown flow and therefore are the correct place to consume `lsp-api`. - -## Scope - -### Included -- Add project-scoped LSP server ownership to the Studio project session lifecycle. -- Boot the server during project open. -- Shutdown the server during project close. -- Preserve existing shell, packer, play/stop, and debug flows. - -### Excluded -- Rich semantic responses. -- Automation channel work. -- VS Code extension transport changes. - -## Non-Goals - -- Cross-project shared server process management. -- Multi-project pooling or server reuse. -- Changing the overall launcher/window model. - -## Execution Steps - -### Step 1 - Extend project session ownership to include the LSP lifecycle boundary - -**What:** Make `StudioProjectSession` own the new project-scoped LSP service reference. -**How:** Add the minimal `lsp-api` contract to `StudioProjectSession`, ensure it is initialized by `StudioProjectSessionFactory`, and guarantee shutdown on `close()`, including failure-safe teardown ordering. -**File(s):** `prometeu-studio/src/main/java/p/studio/projectsessions/StudioProjectSession.java`, `prometeu-studio/src/main/java/p/studio/projectsessions/StudioProjectSessionFactory.java`, related tests. - -### Step 2 - Trigger boot during project open flow - -**What:** Start the LSP server as part of project initialization. -**How:** Update the project-open sequence so the server boots after the project context is ready and before the project window is considered fully opened. Ensure failures surface as project-open failures instead of becoming silent background errors. -**File(s):** `prometeu-studio/src/main/java/p/studio/window/StudioWindowCoordinator.java`, possibly `prometeu-app/src/main/java/p/studio/AppContainer.java` and `prometeu-studio/src/main/java/p/studio/Container.java` if dependency injection changes are needed. - -### Step 3 - Trigger shutdown during project close flow - -**What:** Cleanly stop the project-bound server when the project closes. -**How:** Ensure the existing project close path tears down the LSP service through the session close path, with no leaked socket listener or hanging background resources. -**File(s):** `prometeu-studio/src/main/java/p/studio/window/StudioWindowCoordinator.java`, `prometeu-studio/src/main/java/p/studio/projectsessions/StudioProjectSession.java`. - -### Step 4 - Preserve current dumb connectivity semantics - -**What:** Keep the initial server behavior intentionally simple while validating lifecycle. -**How:** Wire the server so the VS Code extension can still connect over TCP, even if the server behavior remains a minimal handshake or stubbed capability set for now. -**File(s):** `prometeu-lsp/prometeu-lsp-v1/src/main/java/**`, `tools/vscode-extension/src/extension.ts` only if configuration or expectations need adjustment. - -## Test Requirements - -### Unit Tests -- Verify project session close calls LSP shutdown exactly once. -- Verify boot failures are surfaced deterministically during project open. -- Verify repeated close remains idempotent. - -### Integration Tests -- Run `prometeu-studio` tests covering project open/close lifecycle. -- Add a focused integration test proving a project-scoped server is booted and then shut down. - -### Manual Verification -- Open a Studio project, confirm the server starts. -- Close the project, confirm the server port is released and the process/resources terminate. -- Connect via the existing VS Code extension and confirm the dumb server remains reachable. - -## Acceptance Criteria - -- [x] Opening a Studio project boots an LSP server for that project. -- [x] Closing the project shuts down that server. -- [x] The lifecycle is owned by project session boundaries, not global app startup. -- [x] Existing non-LSP project flows remain operational. -- [x] The current dumb connectivity workflow remains usable as a temporary implementation phase. - -## Dependencies - -- `DEC-0032` accepted and normatively locked. -- `PLN-0065` providing the new module and API boundary. - -## Risks - -- Startup ordering mistakes can make project open flaky or hide boot errors. -- Shutdown ordering mistakes can leak ports or threads. -- Lifecycle wiring can accidentally reintroduce global process ownership if the session boundary is not kept strict. diff --git a/discussion/workflow/plans/PLN-0067-compiler-backed-dumb-lsp-server-baseline.md b/discussion/workflow/plans/PLN-0067-compiler-backed-dumb-lsp-server-baseline.md deleted file mode 100644 index b9e652ce..00000000 --- a/discussion/workflow/plans/PLN-0067-compiler-backed-dumb-lsp-server-baseline.md +++ /dev/null @@ -1,100 +0,0 @@ ---- -id: PLN-0067 -ticket: studio-new-lsp-api-and-v1-boundary -title: Compiler-Backed Dumb LSP Server Baseline -status: done -created: 2026-05-05 -completed: 2026-05-05 -tags: [studio, lsp, compiler, baseline, protocol, vscode] ---- - -## Objective - -Establish a maintainable, compiler-backed baseline inside `lsp-v1` that keeps the server behavior deliberately simple while creating the seams required for later semantic layering. - -## Background - -`DEC-0032` explicitly allows wave 1 to remain semantically thin, but it forbids keeping an ad hoc mock structure as the long-term coding pattern. The backend therefore needs a baseline that is: - -- dumb in behavior when necessary, -- but already correctly composed over `compiler` services, -- and already structured for layered enrichment later. - -## Scope - -### Included -- Create compiler-facing service seams used by `lsp-v1`. -- Provide a small, explicit set of LSP capabilities or responses that prove the adapter shape. -- Keep the VS Code extension compatible with the current TCP model. -- Document the temporary behavioral limits in code and tests. - -### Excluded -- Full diagnostics, definition, symbols, inlay hints, or multi-file semantic completeness. -- Automation channel work. -- Non-TCP transport experiments. - -## Non-Goals - -- Matching the full final language feature set. -- Recreating the deleted legacy `prometeu-lsp` behavior. -- Optimizing for performance before the baseline structure is validated. - -## Execution Steps - -### Step 1 - Define compiler-facing bridge services inside `lsp-v1` - -**What:** Introduce explicit bridge classes or adapters between protocol handlers and `compiler`. -**How:** Create narrow services inside `lsp-v1` that own calls into `compiler` entrypoints. Even if the first concrete responses are stubbed or partial, the protocol handlers must already call through these seams instead of embedding compiler knowledge everywhere. -**File(s):** `prometeu-lsp/prometeu-lsp-v1/src/main/java/**`, relevant `prometeu-compiler` integration points when discoverable. - -### Step 2 - Implement a minimal but structured capability slice - -**What:** Keep the server intentionally dumb, but no longer structurally improvised. -**How:** Choose a small capability surface such as `initialize`, `shutdown`, and one lightweight language feature or health response. The exact feature set may stay narrow, but the code must already follow the final layering: - -- protocol request handling, -- bridge service invocation, -- result mapping. - -**File(s):** `prometeu-lsp/prometeu-lsp-v1/src/main/java/**`, potentially `tools/vscode-extension/src/extension.ts` if initialization expectations need tightening. - -### Step 3 - Codify temporary behavior limits - -**What:** Make the current limitations explicit instead of implicit. -**How:** Add tests and lightweight documentation/comments that define the intentionally supported baseline behavior so future work can add capability in layers without guessing what the "mock" currently means. -**File(s):** `prometeu-lsp/prometeu-lsp-v1/src/test/java/**`, targeted source comments where they reduce ambiguity. - -## Test Requirements - -### Unit Tests -- Verify protocol handlers call the correct bridge services. -- Verify compiler bridge services can be instantiated and return stable baseline results. -- Verify no handler bypasses the bridge layer to embed semantic logic ad hoc. - -### Integration Tests -- Run a targeted Studio/LSP integration proving the VS Code client can initialize against the dumb server. -- Run compiler-related tests needed to validate the consumed service seams. - -### Manual Verification -- Connect from VS Code and confirm the server initializes and remains stable. -- Confirm the limited capability set behaves predictably and does not masquerade as richer support than actually implemented. - -## Acceptance Criteria - -- [x] `lsp-v1` talks to `compiler` through explicit bridge services. -- [x] The baseline server behavior remains intentionally simple but structurally clean. -- [x] At least one minimal end-to-end capability slice proves the final layering. -- [x] The extension can still connect over TCP without protocol regressions. -- [x] Temporary semantic limits are explicit in tests and code structure. - -## Dependencies - -- `DEC-0032` accepted and normatively locked. -- `PLN-0065` for module/boundary setup. -- `PLN-0066` for project-scoped lifecycle integration. - -## Risks - -- A "temporary" dumb server can calcify unless the seams are truly explicit and tested. -- Over-stubbing can hide compiler integration issues that should be surfaced early. -- Picking too many baseline features in this wave can dilute the architectural focus. diff --git a/discussion/workflow/plans/PLN-0072-frontend-semantic-host-projection-contract.md b/discussion/workflow/plans/PLN-0072-frontend-semantic-host-projection-contract.md deleted file mode 100644 index cd4ed79a..00000000 --- a/discussion/workflow/plans/PLN-0072-frontend-semantic-host-projection-contract.md +++ /dev/null @@ -1,119 +0,0 @@ ---- -id: PLN-0072 -ticket: frontend-semantic-host-projection-flexibility -title: Frontend Semantic Host Projection Contract -status: done -created: 2026-05-06 -completed: 2026-05-06 -tags: [compiler, compiler-general, frontend, semantics, host-projection, vscode, pbs] ---- - -## Objective - -Introduce the canonical frontend-authored semantic host projection contract in compiler-general frontend metadata and migrate PBS to publish its first VS Code projection without weakening frontend-owned semantic vocabulary. - -## Background - -`DEC-0034` locks that semantic vocabularies remain frontend-owned and canonical, while hosts such as VS Code consume declarative projection metadata authored by the frontend. The current semantic presentation work already establishes frontend-owned themes through `DEC-0033`, but semantic adaptation still lacks a structured host projection contract. - -PBS is the first concrete frontend and therefore the first migration target, but the contract MUST remain compiler-general rather than PBS-shaped. - -## Scope - -### Included -- Evolve compiler/frontend metadata to publish declarative semantic host projection descriptors. -- Define the contract shape for VS Code semantic token projection. -- Migrate PBS to author VS Code projection metadata for its canonical semantic keys. -- Add tests that lock the contract and prevent host-owned remapping logic from becoming the source of truth. - -### Excluded -- LSP transport changes. -- VS Code extension runtime consumption changes. -- Redesigning PBS canonical semantic keys to mimic VS Code categories. - -## Non-Goals - -- Introducing a global rigid semantic taxonomy across frontends. -- Making VS Code semantic token types the canonical frontend semantic contract. -- Solving projection for every future host in the first wave. - -## Execution Steps - -### Step 1 - Define compiler-general host projection metadata - -**What:** Extend the frontend semantic metadata surfaces to carry host projection descriptors alongside canonical semantic keys. -**How:** Add or evolve compiler-general model types so a frontend can declare, for each host projection entry: - -1. the canonical frontend semantic key being projected, -2. the target host identity, -3. the host token type or equivalent target category, -4. any host modifiers, -5. fallback projection semantics when the host cannot represent the key exactly. - -The contract MUST preserve the frontend semantic key as canonical and MUST treat projection as derivative metadata. -**File(s):** `prometeu-compiler/prometeu-compiler-core/src/main/java/p/studio/compiler/models/**`, related frontend definition surfaces. - -### Step 2 - Make projection rules operational and mechanically consumable - -**What:** Turn the projection contract into an exact operational surface rather than an informal note. -**How:** Define invariants, null/empty behavior, and lookup rules for projection descriptors, including: - -1. host identifier semantics, -2. duplicate or conflicting projection handling, -3. missing projection behavior, -4. fallback behavior representation, -5. safe access patterns from `FrontendSpec`. - -The result MUST allow host adapters to translate frontend-authored projection data mechanically without semantic reinterpretation. -**File(s):** `prometeu-compiler/prometeu-compiler-core/src/main/java/**`, associated compiler-general tests. - -### Step 3 - Migrate PBS to author its first VS Code projection - -**What:** Make PBS publish its VS Code semantic projection through the new contract. -**How:** Update PBS frontend metadata so its canonical semantic keys remain unchanged while the frontend also declares how each key projects into VS Code semantic token types and modifiers. The authored projection MUST live in PBS frontend metadata and MUST NOT be reauthored inside the extension. -**File(s):** `prometeu-compiler/frontends/prometeu-frontend-pbs/src/main/java/**`, related PBS semantic presentation tests. - -### Step 4 - Lock the contract with tests - -**What:** Prevent future drift toward host-owned semantic policy. -**How:** Add tests that assert: - -1. frontends publish projection descriptors through compiler-general metadata, -2. PBS canonical keys remain frontend-owned, -3. PBS VS Code projection resolves mechanically from frontend metadata, -4. no global repository-wide rigid semantic taxonomy is introduced as the canonical contract. - -**File(s):** compiler-general and PBS test suites. - -## Test Requirements - -### Unit Tests -- Validate projection model invariants, including required frontend key linkage and host target fields. -- Validate `FrontendSpec` safely exposes host projection metadata. -- Validate missing and duplicate projection handling. - -### Integration Tests -- Run targeted compiler and PBS tests proving host projection metadata compiles, resolves, and remains discoverable through frontend definitions. - -### Manual Verification -- Inspect PBS frontend metadata and confirm the VS Code projection is authored there rather than in host adapter code. -- Confirm canonical PBS semantic keys remain readable and unchanged in ownership terms. - -## Acceptance Criteria - -- [ ] Compiler-general frontend metadata publishes declarative host projection descriptors. -- [ ] The contract preserves canonical frontend semantic keys as the source of truth. -- [ ] The contract supports a VS Code projection without forcing a global rigid taxonomy. -- [ ] PBS authors its VS Code semantic projection through the new contract. -- [ ] Tests lock the contract against host-owned semantic remapping drift. - -## Dependencies - -- `DEC-0034` accepted and normatively locked. -- `DEC-0033` accepted where semantic presentation metadata already exists and may need coordinated evolution. - -## Risks - -- Overfitting projection fields to PBS or to VS Code would weaken future frontend flexibility. -- Allowing ambiguous projection semantics would push semantic authorship back into adapters. -- Collapsing canonical keys into host-shaped aliases would violate `DEC-0034`. diff --git a/discussion/workflow/plans/PLN-0073-lsp-semantic-host-projection-transport.md b/discussion/workflow/plans/PLN-0073-lsp-semantic-host-projection-transport.md deleted file mode 100644 index 038e6bad..00000000 --- a/discussion/workflow/plans/PLN-0073-lsp-semantic-host-projection-transport.md +++ /dev/null @@ -1,107 +0,0 @@ ---- -id: PLN-0073 -ticket: frontend-semantic-host-projection-flexibility -title: LSP Semantic Host Projection Transport -status: done -created: 2026-05-06 -completed: 2026-05-06 -tags: [lsp, compiler, frontend, semantics, host-projection, vscode, protocol] ---- - -## Objective - -Transport canonical frontend semantic vocabulary and frontend-authored VS Code host projection metadata through the Prometeu LSP boundary without normalizing semantic meaning inside the transport layer. - -## Background - -`DEC-0034` requires LSP to carry both canonical frontend semantic keys and frontend-authored host projection metadata, while preserving the ownership boundary between frontend semantics and host adaptation. `DEC-0033` already introduced frontend-authored visual themes through the LSP handshake; semantic host projection must now follow the same ownership model. - -## Scope - -### Included -- Extend LSP-facing baseline message models to carry semantic host projection metadata. -- Update the compiler-backed language service bridge to resolve and expose that metadata from frontend definitions. -- Update the LSP protocol mapper to publish the transported metadata to the VS Code extension. -- Add tests that prove canonical keys and projection metadata are both preserved across transport. - -### Excluded -- Defining the compiler-general projection contract itself. -- Applying the projection inside the VS Code extension. -- Redesigning semantic token classification logic beyond what is needed to expose projection metadata. - -## Non-Goals - -- Performing semantic normalization inside the LSP layer. -- Collapsing frontend semantic keys into host token types in baseline message models. -- Introducing host-specific semantic rules into `lsp-api` that belong to frontend metadata. - -## Execution Steps - -### Step 1 - Extend baseline transport models for semantic projection - -**What:** Add baseline message shapes that can carry semantic host projection metadata. -**How:** Evolve LSP-facing DTOs so the server description or related handshake payload can transport: - -1. frontend language identity, -2. canonical frontend semantic keys, -3. one or more host projection entries for VS Code, -4. any fallback metadata required by the projection contract. - -The transport model MUST preserve canonical frontend keys explicitly rather than flattening everything into host token types. -**File(s):** `prometeu-lsp/prometeu-lsp-api/src/main/java/**`, `prometeu-lsp/prometeu-lsp-v1/src/main/java/p/studio/lsp/messages/**`. - -### Step 2 - Resolve transport payload from compiler frontend metadata - -**What:** Make the language service bridge expose semantic host projection metadata from the frontend contract. -**How:** Update compiler-backed bridge code to read canonical semantic keys plus VS Code projection descriptors from the frontend definition and map them into the baseline transport payload without reinterpreting semantic meaning. -**File(s):** `prometeu-lsp/prometeu-lsp-v1/src/main/java/p/studio/lsp/services/compiler/**`. - -### Step 3 - Publish the projection payload through the handshake - -**What:** Make the VS Code client able to receive semantic projection metadata at initialization time. -**How:** Update the protocol mapping layer so the initialize result transports canonical semantic keys and VS Code projection metadata through the agreed experimental surface or another current handshake surface, while keeping semantic theming transport from `DEC-0033` intact and coherent. -**File(s):** `prometeu-lsp/prometeu-lsp-v1/src/main/java/p/studio/lsp/services/protocol/mapping/**`, related server description surfaces. - -### Step 4 - Lock transport behavior with tests - -**What:** Prevent future drift toward semantic normalization inside LSP. -**How:** Add tests that assert: - -1. canonical frontend semantic keys survive transport, -2. VS Code projection entries survive transport, -3. payload structure remains mechanically consumable by the extension, -4. the transport layer does not replace frontend keys with host token categories. - -**File(s):** `prometeu-lsp/prometeu-lsp-v1/src/test/java/**`, `prometeu-lsp/prometeu-lsp-api` tests if present. - -## Test Requirements - -### Unit Tests -- Validate mapping from frontend projection metadata into baseline transport DTOs. -- Validate transport serialization of canonical keys plus projection entries. - -### Integration Tests -- Run targeted `lsp-v1` tests proving the server handshake exposes both semantic themes and semantic host projection coherently. - -### Manual Verification -- Inspect the initialize payload and confirm that frontend semantic keys and VS Code projection metadata are both visible. -- Confirm no layer in LSP rewrites canonical semantic keys into a mandatory host taxonomy. - -## Acceptance Criteria - -- [ ] LSP transport models carry canonical frontend semantic keys and VS Code projection metadata together. -- [ ] The compiler-backed bridge resolves that metadata directly from frontend definitions. -- [ ] The initialize payload exposes the metadata mechanically to the extension. -- [ ] Tests lock the transport layer against semantic normalization drift. - -## Dependencies - -- `DEC-0034` accepted and normatively locked. -- `PLN-0072` completes the compiler/frontend projection contract. -- `DEC-0033` transport conventions remain in force for visual theme payloads. - -## Risks - -- Reusing visual theme payload structures carelessly could blur the boundary between visual and semantic contracts. -- Flattening transport too aggressively could erase canonical frontend key identity. -- Excessive protocol specialization could make future hosts harder to add. diff --git a/discussion/workflow/plans/PLN-0074-vscode-semantic-host-projection-adapter.md b/discussion/workflow/plans/PLN-0074-vscode-semantic-host-projection-adapter.md deleted file mode 100644 index 53bc1fc3..00000000 --- a/discussion/workflow/plans/PLN-0074-vscode-semantic-host-projection-adapter.md +++ /dev/null @@ -1,109 +0,0 @@ ---- -id: PLN-0074 -ticket: frontend-semantic-host-projection-flexibility -title: VS Code Semantic Host Projection Adapter -status: done -created: 2026-05-06 -completed: 2026-05-06 -tags: [vscode, extension, frontend, semantics, host-projection, adapter] ---- - -## Objective - -Make the VS Code extension consume frontend-authored semantic host projection metadata mechanically so semantic highlighting behavior no longer depends on extension-owned assumptions about frontend semantic key names. - -## Background - -`DEC-0034` makes the frontend semantic vocabulary canonical and requires VS Code adaptation to follow frontend-authored projection metadata rather than an extension-owned taxonomy. `DEC-0033` already moved visual theme ownership into frontend-authored runtime payloads; the semantic adapter must now follow the same model. - -The current extension still contains assumptions about semantic token naming and package-level declarations that do not fully reflect frontend-authored projection data. - -## Scope - -### Included -- Consume semantic host projection payload from the LSP handshake. -- Translate frontend-authored VS Code projection descriptors into the extension's semantic token registration and runtime theme application flow. -- Reduce extension-owned semantic assumptions to the minimum static structure the VS Code platform requires. -- Add tests or verification hooks that prove the adapter follows frontend-authored projection data mechanically. - -### Excluded -- Inventing or redefining canonical semantic meaning inside the extension. -- Reworking compiler semantic classification beyond consuming the delivered keys and projections. -- Solving projection for non-VS Code hosts. - -## Non-Goals - -- Making the extension the owner of semantic taxonomy policy. -- Hardcoding PBS-specific semantic mapping logic as the authoritative source. -- Guaranteeing a perfect one-to-one rendering match with Studio for every frontend key. - -## Execution Steps - -### Step 1 - Update extension-side semantic projection models - -**What:** Add extension-side runtime shapes for the transported semantic projection payload. -**How:** Extend the VS Code extension client code so it can read and store: - -1. canonical frontend semantic keys, -2. VS Code projection entries per key, -3. fallback metadata if present, -4. any language-scoped identity needed to apply the projection safely. - -These runtime shapes MUST reflect transported frontend-authored metadata rather than a hand-maintained extension mapping table. -**File(s):** `tools/vscode-extension/src/**`, generated `out/**` mirror as needed. - -### Step 2 - Apply projection mechanically in the semantic adapter path - -**What:** Make the extension derive VS Code-facing semantic behavior from the transported projection. -**How:** Update extension logic so semantic token registration, selectors, and any runtime semantic color rule generation consume the frontend-authored projection entries. The adapter MUST treat missing projection data as a fallback condition, not as permission to reauthor semantic meaning broadly in extension code. -**File(s):** `tools/vscode-extension/src/extension.ts`, related extension helper modules if introduced, generated `out/**` mirror as needed. - -### Step 3 - Minimize static package-level semantic assumptions - -**What:** Reduce static `package.json` semantic declarations to the minimum platform-required scaffolding. -**How:** Audit the extension manifest and runtime so static declarations remain only where VS Code requires them structurally. Any semantic mapping policy that can be expressed by frontend-authored projection data MUST move out of the manifest and into runtime translation logic. -**File(s):** `tools/vscode-extension/package.json`, `tools/vscode-extension/src/**`. - -### Step 4 - Lock adapter behavior with tests and verification - -**What:** Prevent regression toward extension-owned semantic policy. -**How:** Add tests or targeted verification code that assert: - -1. the adapter reads frontend-authored projection payloads, -2. semantic rules derive from projection data rather than hardcoded PBS assumptions, -3. fallback paths stay bounded and explicit, -4. frontend projection updates do not require extension semantic remapping edits for ordinary token adjustments. - -**File(s):** extension test surfaces if present, otherwise targeted runtime assertions and documented manual verification paths. - -## Test Requirements - -### Unit Tests -- Validate parsing of semantic projection payloads from the initialize response. -- Validate transformation from projection entries into VS Code semantic token rule inputs. - -### Integration Tests -- If extension test infrastructure exists, verify that a mock initialize payload drives semantic adapter behavior without code-level remapping tables. - -### Manual Verification -- Reload the extension and inspect runtime behavior with a PBS project to confirm semantic highlighting is driven by transported projection data. -- Confirm that a frontend-authored projection change would only require frontend/LSP updates, not new semantic mapping logic in the extension. - -## Acceptance Criteria - -- [ ] The extension consumes canonical semantic keys and VS Code projection metadata from the LSP handshake. -- [ ] Semantic adapter behavior derives mechanically from transported projection data. -- [ ] Static extension manifest assumptions are reduced to platform-required scaffolding. -- [ ] The extension no longer acts as the authoritative source of frontend semantic mapping policy. - -## Dependencies - -- `DEC-0034` accepted and normatively locked. -- `PLN-0073` completes LSP transport of semantic host projection metadata. -- `DEC-0033` dynamic visual theme translation remains in place and coherent with semantic adaptation. - -## Risks - -- VS Code manifest constraints may still require some static declarations, and those boundaries must stay explicit. -- Weak fallback rules could accidentally recreate extension-owned semantic policy. -- Failure to update generated extension output alongside source would leave the runtime out of sync in the current local environment. diff --git a/prometeu-compiler/frontends/prometeu-frontend-pbs/src/main/resources/themes/pbs/semantic-highlighting.css b/prometeu-compiler/frontends/prometeu-frontend-pbs/src/main/resources/themes/pbs/semantic-highlighting.css deleted file mode 100644 index 801b2730..00000000 --- a/prometeu-compiler/frontends/prometeu-frontend-pbs/src/main/resources/themes/pbs/semantic-highlighting.css +++ /dev/null @@ -1,111 +0,0 @@ -.editor-workspace-code-area-type-pbs { - -fx-highlight-fill: #2d4f6b; -} - -.editor-workspace-code-area-type-pbs .text { - -fx-fill: #d9e2ec; -} - -.editor-workspace-code-area-type-pbs .lineno { - -fx-text-fill: #6f8193; -} - -.editor-workspace-code-area-type-pbs .text.editor-semantic-pbs-keyword { - -fx-fill: #569cd6; -} - -.editor-workspace-code-area-type-pbs .text.editor-semantic-pbs-lifecycle { - -fx-fill: #ef50c0; -} - -.editor-workspace-code-area-type-pbs .text.editor-semantic-pbs-function { - -fx-fill: #f2c14e; -} - -.editor-workspace-code-area-type-pbs .text.editor-semantic-pbs-method { - -fx-fill: #f2c14e; -} - -.editor-workspace-code-area-type-pbs .text.editor-semantic-pbs-constructor { - -fx-fill: #ecdcaa; -} - -.editor-workspace-code-area-type-pbs .text.editor-semantic-pbs-struct { - -fx-fill: #4ec9b0; -} - -.editor-workspace-code-area-type-pbs .text.editor-semantic-pbs-contract { - -fx-fill: #78dce8; -} - -.editor-workspace-code-area-type-pbs .text.editor-semantic-pbs-host { - -fx-fill: #b7a2fa; -} - -.editor-workspace-code-area-type-pbs .text.editor-semantic-pbs-builtin-type { - -fx-fill: #8be9fd; -} - -.editor-workspace-code-area-type-pbs .text.editor-semantic-pbs-service { - -fx-fill: #b7a2fa; -} - -.editor-workspace-code-area-type-pbs .text.editor-semantic-pbs-error { - -fx-fill: #ff5b5b; -} - -.editor-workspace-code-area-type-pbs .text.editor-semantic-pbs-enum { - -fx-fill: #56cfe1; -} - -.editor-workspace-code-area-type-pbs .text.editor-semantic-pbs-callback { - -fx-fill: #b7a2fa; -} - -.editor-workspace-code-area-type-pbs .text.editor-semantic-pbs-global { - -fx-fill: #f790fc; - -fx-font-style: italic; -} - -.editor-workspace-code-area-type-pbs .text.editor-semantic-pbs-const { - -fx-fill: #f78c6c; -} - -.editor-workspace-code-area-type-pbs .text.editor-semantic-pbs-implements { - -fx-fill: #a1c181; -} - -.editor-workspace-code-area-type-pbs .text.editor-semantic-pbs-string { - -fx-fill: #00c088; -} - -.editor-workspace-code-area-type-pbs .text.editor-semantic-pbs-number { - -fx-fill: #ff90b0; -} - -.editor-workspace-code-area-type-pbs .text.editor-semantic-pbs-comment { - -fx-fill: #c090b0; - -fx-font-style: italic; -} - -.editor-workspace-code-area-type-pbs .text.editor-semantic-pbs-literal { - -fx-fill: #4fc1ff; -} - -.editor-workspace-code-area-type-pbs .text.editor-semantic-pbs-operator { - -fx-fill: #d4d4d4; -} - -.editor-workspace-code-area-type-pbs .text.editor-semantic-pbs-punctuation { - -fx-fill: #d4d4d4; -} - -.editor-workspace-code-area-type-pbs .text.editor-semantic-pbs-identifier { - -fx-fill: #d4d4d4; -} - -.editor-workspace-status-chip-type-pbs { - -fx-background-color: #2c2140; - -fx-border-color: #a47dff; - -fx-text-fill: #efe6ff; -} -- 2.47.2 From ef814b2420681538d2649d63dab063e2fc230241 Mon Sep 17 00:00:00 2001 From: bQUARKz Date: Fri, 8 May 2026 09:17:43 +0100 Subject: [PATCH 32/37] housekeeping --- .../.backups/index.ndjson.20260331-092554.bak | 13 -- .../.backups/index.ndjson.20260508-091553.bak | 35 ++++ discussion/index.ndjson | 6 +- ...-stack-before-rebuilding-code-workflows.md | 84 ++++++++++ ...h-structured-contract-and-host-adapters.md | 93 +++++++++++ ...034-vscode-editor-migration-feasibility.md | 106 ------------ ...nd-visual-theme-spec-and-css-retirement.md | 147 ----------------- ...EC-0031-studio-editor-workspace-cleanup.md | 148 ----------------- ...nd-visual-theme-spec-and-css-retirement.md | 152 ------------------ ...-and-state-cleanup-after-editor-removal.md | 91 ----------- ...odule-removal-with-runtime-preservation.md | 91 ----------- ...lesson-cleanup-for-editor-stack-removal.md | 90 ----------- ...ntend-visual-contract-and-pbs-migration.md | 118 -------------- ...sp-visual-theme-transport-and-selection.md | 114 ------------- ...visual-theme-adapter-and-css-retirement.md | 101 ------------ ...scode-dynamic-theme-translation-adapter.md | 100 ------------ 16 files changed, 215 insertions(+), 1274 deletions(-) delete mode 100644 discussion/.backups/index.ndjson.20260331-092554.bak create mode 100644 discussion/.backups/index.ndjson.20260508-091553.bak create mode 100644 discussion/lessons/DSC-0031-studio-editor-workspace-cleanup/LSN-0049-remove-the-embedded-editor-stack-before-rebuilding-code-workflows.md create mode 100644 discussion/lessons/DSC-0033-frontend-visual-theme-spec-and-css-retirement/LSN-0050-frontend-owned-visual-themes-with-structured-contract-and-host-adapters.md delete mode 100644 discussion/workflow/agendas/AGD-0034-vscode-editor-migration-feasibility.md delete mode 100644 discussion/workflow/agendas/AGD-0036-frontend-visual-theme-spec-and-css-retirement.md delete mode 100644 discussion/workflow/decisions/DEC-0031-studio-editor-workspace-cleanup.md delete mode 100644 discussion/workflow/decisions/DEC-0033-frontend-visual-theme-spec-and-css-retirement.md delete mode 100644 discussion/workflow/plans/PLN-0062-shell-session-and-state-cleanup-after-editor-removal.md delete mode 100644 discussion/workflow/plans/PLN-0063-legacy-lsp-and-vfs-module-removal-with-runtime-preservation.md delete mode 100644 discussion/workflow/plans/PLN-0064-normative-test-and-lesson-cleanup-for-editor-stack-removal.md delete mode 100644 discussion/workflow/plans/PLN-0068-frontend-visual-contract-and-pbs-migration.md delete mode 100644 discussion/workflow/plans/PLN-0069-lsp-visual-theme-transport-and-selection.md delete mode 100644 discussion/workflow/plans/PLN-0070-studio-visual-theme-adapter-and-css-retirement.md delete mode 100644 discussion/workflow/plans/PLN-0071-vscode-dynamic-theme-translation-adapter.md diff --git a/discussion/.backups/index.ndjson.20260331-092554.bak b/discussion/.backups/index.ndjson.20260331-092554.bak deleted file mode 100644 index 1945b847..00000000 --- a/discussion/.backups/index.ndjson.20260331-092554.bak +++ /dev/null @@ -1,13 +0,0 @@ -{"type":"meta","next_id":{"DSC":13,"AGD":13,"DEC":10,"PLN":19,"LSN":27,"CLSN":1}} -{"type":"discussion","id":"DSC-0001","status":"done","ticket":"studio-docs-import","title":"Import docs/studio into discussion-framework artifacts","created_at":"2026-03-26","updated_at":"2026-03-26","tags":["studio","migration","discussion-framework","docs-import"],"agendas":[],"decisions":[],"plans":[],"lessons":[{"id":"LSN-0001","file":"discussion/lessons/DSC-0001-studio-docs-import/LSN-0001-assets-workspace-execution-wave-legacy.md","status":"done","created_at":"2026-03-26","updated_at":"2026-03-26"},{"id":"LSN-0002","file":"discussion/lessons/DSC-0001-studio-docs-import/LSN-0002-bank-composition-editor-legacy.md","status":"done","created_at":"2026-03-26","updated_at":"2026-03-26"},{"id":"LSN-0003","file":"discussion/lessons/DSC-0001-studio-docs-import/LSN-0003-mental-model-asset-mutations-legacy.md","status":"done","created_at":"2026-03-26","updated_at":"2026-03-26"},{"id":"LSN-0004","file":"discussion/lessons/DSC-0001-studio-docs-import/LSN-0004-mental-model-assets-workspace-legacy.md","status":"done","created_at":"2026-03-26","updated_at":"2026-03-26"},{"id":"LSN-0005","file":"discussion/lessons/DSC-0001-studio-docs-import/LSN-0005-mental-model-studio-events-and-components-legacy.md","status":"done","created_at":"2026-03-26","updated_at":"2026-03-26"},{"id":"LSN-0006","file":"discussion/lessons/DSC-0001-studio-docs-import/LSN-0006-mental-model-studio-shell-legacy.md","status":"done","created_at":"2026-03-26","updated_at":"2026-03-26"},{"id":"LSN-0007","file":"discussion/lessons/DSC-0001-studio-docs-import/LSN-0007-pack-wizard-shell-legacy.md","status":"done","created_at":"2026-03-26","updated_at":"2026-03-26"},{"id":"LSN-0008","file":"discussion/lessons/DSC-0001-studio-docs-import/LSN-0008-project-scoped-state-and-activity-legacy.md","status":"done","created_at":"2026-03-26","updated_at":"2026-03-26"},{"id":"LSN-0016","file":"discussion/lessons/DSC-0001-studio-docs-import/LSN-0016-studio-docs-import-pattern.md","status":"done","created_at":"2026-03-26","updated_at":"2026-03-26"}]} -{"type":"discussion","id":"DSC-0002","status":"open","ticket":"palette-management-in-studio","title":"Palette Management in Studio","created_at":"2026-03-26","updated_at":"2026-03-26","tags":["studio","legacy-import","palette-management","tile-bank","packer-boundary"],"agendas":[{"id":"AGD-0002","file":"AGD-0002-palette-management-in-studio.md","status":"open","created_at":"2026-03-26","updated_at":"2026-03-26"}],"decisions":[],"plans":[],"lessons":[]} -{"type":"discussion","id":"DSC-0003","status":"done","ticket":"packer-docs-import","title":"Import docs/packer into discussion-framework artifacts","created_at":"2026-03-26","updated_at":"2026-03-26","tags":["packer","migration","discussion-framework","docs-import"],"agendas":[],"decisions":[],"plans":[],"lessons":[{"id":"LSN-0009","file":"discussion/lessons/DSC-0003-packer-docs-import/LSN-0009-mental-model-packer-legacy.md","status":"done","created_at":"2026-03-26","updated_at":"2026-03-26"},{"id":"LSN-0010","file":"discussion/lessons/DSC-0003-packer-docs-import/LSN-0010-asset-identity-and-runtime-contract-legacy.md","status":"done","created_at":"2026-03-26","updated_at":"2026-03-26"},{"id":"LSN-0011","file":"discussion/lessons/DSC-0003-packer-docs-import/LSN-0011-foundations-workspace-runtime-and-build-legacy.md","status":"done","created_at":"2026-03-26","updated_at":"2026-03-26"},{"id":"LSN-0012","file":"discussion/lessons/DSC-0003-packer-docs-import/LSN-0012-runtime-ownership-and-studio-boundary-legacy.md","status":"done","created_at":"2026-03-26","updated_at":"2026-03-26"},{"id":"LSN-0013","file":"discussion/lessons/DSC-0003-packer-docs-import/LSN-0013-metadata-convergence-and-runtime-sink-legacy.md","status":"done","created_at":"2026-03-26","updated_at":"2026-03-26"},{"id":"LSN-0014","file":"discussion/lessons/DSC-0003-packer-docs-import/LSN-0014-pack-wizard-summary-validation-and-pack-execution-legacy.md","status":"done","created_at":"2026-03-26","updated_at":"2026-03-26"},{"id":"LSN-0015","file":"discussion/lessons/DSC-0003-packer-docs-import/LSN-0015-tile-bank-packing-contract-legacy.md","status":"done","created_at":"2026-03-26","updated_at":"2026-03-26"},{"id":"LSN-0017","file":"discussion/lessons/DSC-0003-packer-docs-import/LSN-0017-packer-docs-import-pattern.md","status":"done","created_at":"2026-03-26","updated_at":"2026-03-26"}]} -{"type":"discussion","id":"DSC-0004","status":"open","ticket":"tilemap-and-metatile-runtime-binary-layout","title":"Tilemap and Metatile Runtime Binary Layout","created_at":"2026-03-26","updated_at":"2026-03-26","tags":["packer","legacy-import","tilemap","metatile","runtime-layout"],"agendas":[{"id":"AGD-0004","file":"AGD-0004-tilemap-and-metatile-runtime-binary-layout.md","status":"open","created_at":"2026-03-26","updated_at":"2026-03-26"}],"decisions":[],"plans":[],"lessons":[]} -{"type":"discussion","id":"DSC-0005","status":"open","ticket":"variable-tile-bank-palette-serialization","title":"Variable Tile Bank Palette Serialization","created_at":"2026-03-26","updated_at":"2026-03-26","tags":["packer","legacy-import","tile-bank","palette-serialization","versioning"],"agendas":[{"id":"AGD-0005","file":"AGD-0005-variable-tile-bank-palette-serialization.md","status":"open","created_at":"2026-03-26","updated_at":"2026-03-26"}],"decisions":[],"plans":[],"lessons":[]} -{"type":"discussion","id":"DSC-0006","status":"done","ticket":"pbs-game-facing-asset-refs-and-call-result-discard","title":"PBS Game-Facing Asset References and Ignored Call Result Lowering","created_at":"2026-03-27","updated_at":"2026-03-30","tags":["compiler","pbs","ergonomics","lowering","runtime","asset-identity","expression-statements"],"agendas":[],"decisions":[],"plans":[],"lessons":[{"id":"LSN-0024","file":"discussion/lessons/DSC-0006-pbs-game-facing-asset-refs-and-call-result-discard/LSN-0024-addressable-surface-host-metadata-and-ignored-value-discipline.md","status":"done","created_at":"2026-03-30","updated_at":"2026-03-30"}]} -{"type":"discussion","id":"DSC-0007","status":"done","ticket":"pbs-learn-to-discussion-lessons-migration","title":"Migrate PBS Learn Documents into Discussion Lessons","created_at":"2026-03-27","updated_at":"2026-03-27","tags":["compiler","pbs","migration","discussion-framework","lessons","learn-prune"],"agendas":[],"decisions":[],"plans":[],"lessons":[{"id":"LSN-0018","file":"discussion/lessons/DSC-0007-pbs-learn-to-discussion-lessons-migration/LSN-0018-pbs-ast-and-parser-contract-legacy.md","status":"done","created_at":"2026-03-27","updated_at":"2026-03-27"},{"id":"LSN-0019","file":"discussion/lessons/DSC-0007-pbs-learn-to-discussion-lessons-migration/LSN-0019-pbs-name-resolution-and-linking-legacy.md","status":"done","created_at":"2026-03-27","updated_at":"2026-03-27"},{"id":"LSN-0020","file":"discussion/lessons/DSC-0007-pbs-learn-to-discussion-lessons-migration/LSN-0020-pbs-runtime-values-identity-memory-boundaries-legacy.md","status":"done","created_at":"2026-03-27","updated_at":"2026-03-27"},{"id":"LSN-0021","file":"discussion/lessons/DSC-0007-pbs-learn-to-discussion-lessons-migration/LSN-0021-pbs-diagnostics-and-conformance-governance-legacy.md","status":"done","created_at":"2026-03-27","updated_at":"2026-03-27"},{"id":"LSN-0022","file":"discussion/lessons/DSC-0007-pbs-learn-to-discussion-lessons-migration/LSN-0022-pbs-globals-lifecycle-and-published-entrypoint-legacy.md","status":"done","created_at":"2026-03-27","updated_at":"2026-03-27"}]} -{"type":"discussion","id":"DSC-0008","status":"done","ticket":"pbs-low-level-asset-manager-surface","title":"PBS Low-Level Asset Manager Surface for Runtime AssetManager","created_at":"2026-03-27","updated_at":"2026-03-27","tags":["compiler","pbs","runtime","asset-manager","host-abi","stdlib","asset"],"agendas":[],"decisions":[],"plans":[],"lessons":[{"id":"LSN-0023","file":"discussion/lessons/DSC-0008-pbs-low-level-asset-manager-surface/LSN-0023-lowassets-runtime-aligned-sdk-surface.md","status":"done","created_at":"2026-03-27","updated_at":"2026-03-27"}]} -{"type":"discussion","id":"DSC-0009","status":"open","ticket":"studio-debugger-workspace-integration","title":"Integrate ../debugger into Studio as a dedicated workspace","created_at":"2026-03-30","updated_at":"2026-03-30","tags":["studio","debugger","workspace","integration","shell"],"agendas":[{"id":"AGD-0009","file":"AGD-0009-studio-debugger-workspace-integration.md","status":"open","created_at":"2026-03-30","updated_at":"2026-03-30"}],"decisions":[],"plans":[],"lessons":[]} -{"type":"discussion","id":"DSC-0010","status":"done","ticket":"studio-code-editor-workspace-foundations","title":"Establish Code Editor workspace foundations in Studio without LSP","created_at":"2026-03-30","updated_at":"2026-03-31","tags":["studio","editor","workspace","multi-frontend","lsp-deferred"],"agendas":[],"decisions":[],"plans":[],"lessons":[{"id":"LSN-0026","file":"discussion/lessons/DSC-0010-studio-code-editor-workspace-foundations/LSN-0026-read-only-editor-foundations-and-semantic-deferral.md","status":"done","created_at":"2026-03-31","updated_at":"2026-03-31"}]} -{"type":"discussion","id":"DSC-0011","status":"done","ticket":"compiler-analyze-compile-build-pipeline-split","title":"Split compiler pipeline into analyze, compile, and build entrypoints","created_at":"2026-03-30","updated_at":"2026-03-30","tags":["compiler","pipeline","artifacts","build","analysis"],"agendas":[],"decisions":[],"plans":[],"lessons":[{"id":"LSN-0025","file":"discussion/lessons/DSC-0011-compiler-analyze-compile-build-pipeline-split/LSN-0025-compiler-pipeline-entrypoints-and-result-boundaries.md","status":"done","created_at":"2026-03-30","updated_at":"2026-03-30"}]} -{"type":"discussion","id":"DSC-0012","status":"open","ticket":"studio-editor-document-vfs-boundary","title":"Definir um boundary de VFS documental para tree/view/open files no Code Editor do Studio","created_at":"2026-03-31","updated_at":"2026-03-31","tags":["studio","editor","workspace","vfs","filesystem","boundary"],"agendas":[{"id":"AGD-0012","file":"AGD-0012-studio-editor-document-vfs-boundary.md","status":"in_progress","created_at":"2026-03-31","updated_at":"2026-03-31"}],"decisions":[{"id":"DEC-0009","file":"DEC-0009-studio-prometeu-vfs-project-document-boundary.md","status":"in_progress","created_at":"2026-03-31","updated_at":"2026-03-31","ref_agenda":"AGD-0012"}],"plans":[{"id":"PLN-0015","file":"PLN-0015-propagate-dec-0009-into-studio-specs.md","status":"done","created_at":"2026-03-31","updated_at":"2026-03-31","ref_decisions":["DEC-0009"]},{"id":"PLN-0016","file":"PLN-0016-build-prometeu-vfs-filesystem-backed-core.md","status":"done","created_at":"2026-03-31","updated_at":"2026-03-31","ref_decisions":["DEC-0009"]},{"id":"PLN-0017","file":"PLN-0017-add-studio-project-session-ownership-for-prometeu-vfs.md","status":"done","created_at":"2026-03-31","updated_at":"2026-03-31","ref_decisions":["DEC-0009"]},{"id":"PLN-0018","file":"PLN-0018-migrate-code-editor-to-prometeu-vfs.md","status":"done","created_at":"2026-03-31","updated_at":"2026-03-31","ref_decisions":["DEC-0009"]}],"lessons":[]} diff --git a/discussion/.backups/index.ndjson.20260508-091553.bak b/discussion/.backups/index.ndjson.20260508-091553.bak new file mode 100644 index 00000000..b88da099 --- /dev/null +++ b/discussion/.backups/index.ndjson.20260508-091553.bak @@ -0,0 +1,35 @@ +{"type":"meta","next_id":{"DSC":35,"AGD":38,"DEC":35,"PLN":75,"LSN":49,"CLSN":1}} +{"type":"discussion","id":"DSC-0034","status":"done","ticket":"frontend-semantic-host-projection-flexibility","title":"Frontend semantic vocabulary flexibility and declarative host projection","created_at":"2026-05-06","updated_at":"2026-05-07","tags":["compiler","compiler-general","frontend","semantics","vscode","host-projection","lsp"],"agendas":[],"decisions":[],"plans":[],"lessons":[{"id":"LSN-0048","file":"discussion/lessons/DSC-0034-frontend-semantic-host-projection-flexibility/LSN-0048-frontend-owned-semantic-vocabularies-with-declarative-host-projection.md","status":"done","created_at":"2026-05-07","updated_at":"2026-05-07"}]} +{"type":"discussion","id":"DSC-0033","status":"in_progress","ticket":"frontend-visual-theme-spec-and-css-retirement","title":"Frontend visual theme spec and retirement of host-consumed semantic CSS","created_at":"2026-05-06","updated_at":"2026-05-06","tags":["compiler","compiler-general","frontend","presentation","theming","studio","vscode","lsp","pbs"],"agendas":[{"id":"AGD-0036","file":"AGD-0036-frontend-visual-theme-spec-and-css-retirement.md","status":"accepted","created_at":"2026-05-06","updated_at":"2026-05-06"}],"decisions":[{"id":"DEC-0033","file":"DEC-0033-frontend-visual-theme-spec-and-css-retirement.md","status":"accepted","created_at":"2026-05-06","updated_at":"2026-05-06","ref_agenda":"AGD-0036"}],"plans":[{"id":"PLN-0068","file":"PLN-0068-frontend-visual-contract-and-pbs-migration.md","status":"open","created_at":"2026-05-06","updated_at":"2026-05-06","ref_decisions":["DEC-0033"]},{"id":"PLN-0069","file":"PLN-0069-lsp-visual-theme-transport-and-selection.md","status":"open","created_at":"2026-05-06","updated_at":"2026-05-06","ref_decisions":["DEC-0033"]},{"id":"PLN-0070","file":"PLN-0070-studio-visual-theme-adapter-and-css-retirement.md","status":"open","created_at":"2026-05-06","updated_at":"2026-05-06","ref_decisions":["DEC-0033"]},{"id":"PLN-0071","file":"PLN-0071-vscode-dynamic-theme-translation-adapter.md","status":"open","created_at":"2026-05-06","updated_at":"2026-05-06","ref_decisions":["DEC-0033"]}],"lessons":[]} +{"type":"discussion","id":"DSC-0032","status":"done","ticket":"studio-new-lsp-api-and-v1-boundary","title":"Novo boundary entre lsp-api, lsp-v1 e a extensao VS Code","created_at":"2026-05-05","updated_at":"2026-05-07","tags":["studio","lsp","vscode","protocol","api","boundary"],"agendas":[],"decisions":[],"plans":[],"lessons":[{"id":"LSN-0047","file":"discussion/lessons/DSC-0032-studio-new-lsp-api-and-v1-boundary/LSN-0047-project-scoped-lsp-boundary-and-protocol-containment.md","status":"done","created_at":"2026-05-07","updated_at":"2026-05-07"}]} +{"type":"discussion","id":"DSC-0031","status":"in_progress","ticket":"studio-editor-workspace-cleanup","title":"Limpeza completa do Workspace Editor do Studio e remoção dos acoplamentos legados","created_at":"2026-05-05","updated_at":"2026-05-05","tags":["studio","editor","cleanup","vfs","lsp","migration"],"agendas":[{"id":"AGD-0034","file":"AGD-0034-vscode-editor-migration-feasibility.md","status":"accepted","created_at":"2026-05-05","updated_at":"2026-05-05"}],"decisions":[{"id":"DEC-0031","file":"DEC-0031-studio-editor-workspace-cleanup.md","status":"in_progress","created_at":"2026-05-05","updated_at":"2026-05-05","ref_agenda":"AGD-0034"}],"plans":[{"id":"PLN-0062","file":"PLN-0062-shell-session-and-state-cleanup-after-editor-removal.md","status":"done","created_at":"2026-05-05","updated_at":"2026-05-05","ref_decisions":["DEC-0031"]},{"id":"PLN-0063","file":"PLN-0063-legacy-lsp-and-vfs-module-removal-with-runtime-preservation.md","status":"done","created_at":"2026-05-05","updated_at":"2026-05-05","ref_decisions":["DEC-0031"]},{"id":"PLN-0064","file":"PLN-0064-normative-test-and-lesson-cleanup-for-editor-stack-removal.md","status":"done","created_at":"2026-05-05","updated_at":"2026-05-05","ref_decisions":["DEC-0031"]}],"lessons":[]} +{"type":"discussion","id":"DSC-0030","status":"done","ticket":"studio-scene-pack-runtime-binary-contract","title":"Studio scene pack contract for runtime SCENE binary payload","created_at":"2026-04-24","updated_at":"2026-05-01","tags":["studio","packer","runtime","scene","asset-pack","binary-format","tiled"],"agendas":[],"decisions":[],"plans":[],"lessons":[{"id":"LSN-0046","file":"discussion/lessons/DSC-0030-studio-scene-pack-runtime-binary-contract/LSN-0046-canonical-scene-owns-editorial-truth-while-pack-stays-request-driven.md","status":"done","created_at":"2026-05-01","updated_at":"2026-05-01"}]} +{"type":"discussion","id":"DSC-0029","status":"done","ticket":"studio-frame-composer-syscall-and-sprite-alignment","title":"Studio Alignment with Runtime FrameComposer Syscalls and Sprite Composition","created_at":"2026-04-18","updated_at":"2026-04-18","tags":["studio","compiler","pbs","stdlib","runtime-alignment","abi","syscall","frame-composer","sprites"],"agendas":[],"decisions":[],"plans":[],"lessons":[{"id":"LSN-0041","file":"discussion/lessons/DSC-0029-studio-frame-composer-syscall-and-sprite-alignment/LSN-0041-composer-must-own-public-sprite-composition.md","status":"done","created_at":"2026-04-18","updated_at":"2026-04-18"}]} +{"type":"discussion","id":"DSC-0028","status":"done","ticket":"studio-tiled-parser-assets-scene-asset-type","title":"Tiled Parser and Scene Asset-Type Ownership in Assets Workspace","created_at":"2026-04-15","updated_at":"2026-04-23","tags":["studio","assets","scene","tiled","parser","asset-type"],"agendas":[],"decisions":[],"plans":[],"lessons":[{"id":"LSN-0045","file":"discussion/lessons/DSC-0028-studio-tiled-parser-assets-scene-asset-type/LSN-0045-asset-owned-scene-bank-and-tiled-xml-workflow.md","status":"done","created_at":"2026-04-23","updated_at":"2026-04-23"}]} +{"type":"discussion","id":"DSC-0027","status":"abandoned","ticket":"studio-scene-workspace","title":"Scene Workspace for SCENE Authoring","created_at":"2026-04-14","updated_at":"2026-04-15","tags":["studio","workspace","scene","tilemap","asset","runtime-alignment"],"agendas":[{"id":"AGD-0029","file":"AGD-0029-studio-scene-workspace.md","status":"abandoned","created_at":"2026-04-14","updated_at":"2026-04-15","_override_reason":"Explicit user request on 2026-04-15 to abandon the accepted agenda and its downstream work."}],"decisions":[{"id":"DEC-0026","file":"DEC-0026-studio-scene-workspace.md","status":"abandoned","created_at":"2026-04-14","updated_at":"2026-04-15","ref_agenda":"AGD-0029","_override_reason":"Explicit user request on 2026-04-15 to abandon the accepted decision and stop using it as normative guidance."}],"plans":[{"id":"PLN-0049","file":"PLN-0049-scene-workspace-spec-and-boundary-propagation.md","status":"abandoned","created_at":"2026-04-14","updated_at":"2026-04-15","ref_decisions":["DEC-0026"],"_override_reason":"Explicit user request on 2026-04-15 to abandon all plans derived from DEC-0026."},{"id":"PLN-0050","file":"PLN-0050-scene-workspace-shell-and-project-state-foundations.md","status":"abandoned","created_at":"2026-04-14","updated_at":"2026-04-15","ref_decisions":["DEC-0026"],"_override_reason":"Explicit user request on 2026-04-15 to abandon all plans derived from DEC-0026."},{"id":"PLN-0051","file":"PLN-0051-scene-artifact-and-assets-handoff-contract.md","status":"abandoned","created_at":"2026-04-14","updated_at":"2026-04-15","ref_decisions":["DEC-0026"],"_override_reason":"Explicit user request on 2026-04-15 to abandon all plans derived from DEC-0026."},{"id":"PLN-0052","file":"PLN-0052-scene-workspace-wave-1-tilemap-editor.md","status":"abandoned","created_at":"2026-04-14","updated_at":"2026-04-15","ref_decisions":["DEC-0026"],"_override_reason":"Explicit user request on 2026-04-15 to abandon all plans derived from DEC-0026."}],"lessons":[]} +{"type":"discussion","id":"DSC-0026","status":"done","ticket":"glyph-bank-naming-alignment-with-runtime","title":"Glyph Bank Naming Alignment with Runtime DEC-0006","created_at":"2026-04-10","updated_at":"2026-04-10","tags":["packer","studio","naming","asset-contract","runtime-alignment","glyph-bank"],"agendas":[],"decisions":[],"plans":[],"lessons":[{"id":"LSN-0040","file":"discussion/lessons/DSC-0026-glyph-bank-naming-alignment-with-runtime/LSN-0040-glyph-bank-artifact-naming-alignment.md","status":"done","created_at":"2026-04-10","updated_at":"2026-04-10"}]} +{"type":"discussion","id":"DSC-0025","status":"done","ticket":"packer-pipeline-metadata-ownership","title":"Pipeline Metadata Ownership and Runtime Contract","created_at":"2026-04-09","updated_at":"2026-04-10","tags":["packer","metadata","runtime-contract","tooling","studio"],"agendas":[],"decisions":[],"plans":[],"lessons":[{"id":"LSN-0039","file":"discussion/lessons/DSC-0025-packer-pipeline-metadata-ownership/LSN-0039-runtime-header-boundary-and-tooling-owned-pipeline-metadata.md","status":"done","created_at":"2026-04-10","updated_at":"2026-04-10"}]} +{"type":"discussion","id":"DSC-0024","status":"done","ticket":"jacoco-reports-consolidation","title":"JaCoCo Reports Consolidation in Gradle","created_at":"2026-04-07","updated_at":"2026-04-07","tags":["infra","gradle","jacoco","coverage","jenkins"],"agendas":[],"decisions":[],"plans":[],"lessons":[{"id":"LSN-0038","file":"discussion/lessons/DSC-0024-jacoco-reports-consolidation/LSN-0038-jacoco-reports-consolidation.md","status":"done","created_at":"2026-04-07","updated_at":"2026-04-07"},{"id":"LSN-0044","file":"discussion/lessons/DSC-0024-jacoco-reports-consolidation/LSN-0044-jenkins-jacoco-alignment.md","status":"done","created_at":"2026-04-07","updated_at":"2026-04-07"}]} +{"type":"discussion","id":"DSC-0001","status":"done","ticket":"studio-docs-import","title":"Import docs/studio into discussion-framework artifacts","created_at":"2026-03-26","updated_at":"2026-03-26","tags":["studio","migration","discussion-framework","docs-import"],"agendas":[],"decisions":[],"plans":[],"lessons":[{"id":"LSN-0001","file":"discussion/lessons/DSC-0001-studio-docs-import/LSN-0001-assets-workspace-execution-wave-legacy.md","status":"done","created_at":"2026-03-26","updated_at":"2026-03-26"},{"id":"LSN-0002","file":"discussion/lessons/DSC-0001-studio-docs-import/LSN-0002-bank-composition-editor-legacy.md","status":"done","created_at":"2026-03-26","updated_at":"2026-03-26"},{"id":"LSN-0003","file":"discussion/lessons/DSC-0001-studio-docs-import/LSN-0003-mental-model-asset-mutations-legacy.md","status":"done","created_at":"2026-03-26","updated_at":"2026-03-26"},{"id":"LSN-0004","file":"discussion/lessons/DSC-0001-studio-docs-import/LSN-0004-mental-model-assets-workspace-legacy.md","status":"done","created_at":"2026-03-26","updated_at":"2026-03-26"},{"id":"LSN-0005","file":"discussion/lessons/DSC-0001-studio-docs-import/LSN-0005-mental-model-studio-events-and-components-legacy.md","status":"done","created_at":"2026-03-26","updated_at":"2026-03-26"},{"id":"LSN-0006","file":"discussion/lessons/DSC-0001-studio-docs-import/LSN-0006-mental-model-studio-shell-legacy.md","status":"done","created_at":"2026-03-26","updated_at":"2026-03-26"},{"id":"LSN-0007","file":"discussion/lessons/DSC-0001-studio-docs-import/LSN-0007-pack-wizard-shell-legacy.md","status":"done","created_at":"2026-03-26","updated_at":"2026-03-26"},{"id":"LSN-0008","file":"discussion/lessons/DSC-0001-studio-docs-import/LSN-0008-project-scoped-state-and-activity-legacy.md","status":"done","created_at":"2026-03-26","updated_at":"2026-03-26"},{"id":"LSN-0016","file":"discussion/lessons/DSC-0001-studio-docs-import/LSN-0016-studio-docs-import-pattern.md","status":"done","created_at":"2026-03-26","updated_at":"2026-03-26"}]} +{"type":"discussion","id":"DSC-0002","status":"done","ticket":"palette-management-in-studio","title":"Palette Management in Studio","created_at":"2026-03-26","updated_at":"2026-04-23","tags":["studio","legacy-import","palette-management","tile-bank","packer-boundary"],"agendas":[],"decisions":[],"plans":[],"lessons":[{"id":"LSN-0042","file":"discussion/lessons/DSC-0002-palette-management-in-studio/LSN-0042-schema-driven-palette-authoring-and-local-metadata-events.md","status":"done","created_at":"2026-04-23","updated_at":"2026-04-23"}]} +{"type":"discussion","id":"DSC-0003","status":"done","ticket":"packer-docs-import","title":"Import docs/packer into discussion-framework artifacts","created_at":"2026-03-26","updated_at":"2026-03-26","tags":["packer","migration","discussion-framework","docs-import"],"agendas":[],"decisions":[],"plans":[],"lessons":[{"id":"LSN-0009","file":"discussion/lessons/DSC-0003-packer-docs-import/LSN-0009-mental-model-packer-legacy.md","status":"done","created_at":"2026-03-26","updated_at":"2026-03-26"},{"id":"LSN-0010","file":"discussion/lessons/DSC-0003-packer-docs-import/LSN-0010-asset-identity-and-runtime-contract-legacy.md","status":"done","created_at":"2026-03-26","updated_at":"2026-03-26"},{"id":"LSN-0011","file":"discussion/lessons/DSC-0003-packer-docs-import/LSN-0011-foundations-workspace-runtime-and-build-legacy.md","status":"done","created_at":"2026-03-26","updated_at":"2026-03-26"},{"id":"LSN-0012","file":"discussion/lessons/DSC-0003-packer-docs-import/LSN-0012-runtime-ownership-and-studio-boundary-legacy.md","status":"done","created_at":"2026-03-26","updated_at":"2026-03-26"},{"id":"LSN-0013","file":"discussion/lessons/DSC-0003-packer-docs-import/LSN-0013-metadata-convergence-and-runtime-sink-legacy.md","status":"done","created_at":"2026-03-26","updated_at":"2026-03-26"},{"id":"LSN-0014","file":"discussion/lessons/DSC-0003-packer-docs-import/LSN-0014-pack-wizard-summary-validation-and-pack-execution-legacy.md","status":"done","created_at":"2026-03-26","updated_at":"2026-03-26"},{"id":"LSN-0015","file":"discussion/lessons/DSC-0003-packer-docs-import/LSN-0015-tile-bank-packing-contract-legacy.md","status":"done","created_at":"2026-03-26","updated_at":"2026-03-26"},{"id":"LSN-0017","file":"discussion/lessons/DSC-0003-packer-docs-import/LSN-0017-packer-docs-import-pattern.md","status":"done","created_at":"2026-03-26","updated_at":"2026-03-26"}]} +{"type":"discussion","id":"DSC-0004","status":"abandoned","ticket":"tilemap-and-metatile-runtime-binary-layout","title":"Tilemap and Metatile Runtime Binary Layout","created_at":"2026-03-26","updated_at":"2026-04-24","tags":["packer","legacy-import","tilemap","metatile","runtime-layout"],"agendas":[{"id":"AGD-0004","file":"AGD-0004-tilemap-and-metatile-runtime-binary-layout.md","status":"abandoned","created_at":"2026-03-26","updated_at":"2026-04-24","_override_reason":"Explicit user request on 2026-04-24 to abandon AGD-0004 because the agenda is no longer valid."}],"decisions":[],"plans":[],"lessons":[]} +{"type":"discussion","id":"DSC-0005","status":"open","ticket":"variable-tile-bank-palette-serialization","title":"Variable Tile Bank Palette Serialization","created_at":"2026-03-26","updated_at":"2026-03-26","tags":["packer","legacy-import","tile-bank","palette-serialization","versioning"],"agendas":[{"id":"AGD-0005","file":"AGD-0005-variable-tile-bank-palette-serialization.md","status":"open","created_at":"2026-03-26","updated_at":"2026-03-26"}],"decisions":[],"plans":[],"lessons":[]} +{"type":"discussion","id":"DSC-0006","status":"done","ticket":"pbs-game-facing-asset-refs-and-call-result-discard","title":"PBS Game-Facing Asset References and Ignored Call Result Lowering","created_at":"2026-03-27","updated_at":"2026-03-30","tags":["compiler","pbs","ergonomics","lowering","runtime","asset-identity","expression-statements"],"agendas":[],"decisions":[],"plans":[],"lessons":[{"id":"LSN-0024","file":"discussion/lessons/DSC-0006-pbs-game-facing-asset-refs-and-call-result-discard/LSN-0024-addressable-surface-host-metadata-and-ignored-value-discipline.md","status":"done","created_at":"2026-03-30","updated_at":"2026-03-30"}]} +{"type":"discussion","id":"DSC-0007","status":"done","ticket":"pbs-learn-to-discussion-lessons-migration","title":"Migrate PBS Learn Documents into Discussion Lessons","created_at":"2026-03-27","updated_at":"2026-03-27","tags":["compiler","pbs","migration","discussion-framework","lessons","learn-prune"],"agendas":[],"decisions":[],"plans":[],"lessons":[{"id":"LSN-0018","file":"discussion/lessons/DSC-0007-pbs-learn-to-discussion-lessons-migration/LSN-0018-pbs-ast-and-parser-contract-legacy.md","status":"done","created_at":"2026-03-27","updated_at":"2026-03-27"},{"id":"LSN-0019","file":"discussion/lessons/DSC-0007-pbs-learn-to-discussion-lessons-migration/LSN-0019-pbs-name-resolution-and-linking-legacy.md","status":"done","created_at":"2026-03-27","updated_at":"2026-03-27"},{"id":"LSN-0020","file":"discussion/lessons/DSC-0007-pbs-learn-to-discussion-lessons-migration/LSN-0020-pbs-runtime-values-identity-memory-boundaries-legacy.md","status":"done","created_at":"2026-03-27","updated_at":"2026-03-27"},{"id":"LSN-0021","file":"discussion/lessons/DSC-0007-pbs-learn-to-discussion-lessons-migration/LSN-0021-pbs-diagnostics-and-conformance-governance-legacy.md","status":"done","created_at":"2026-03-27","updated_at":"2026-03-27"},{"id":"LSN-0022","file":"discussion/lessons/DSC-0007-pbs-learn-to-discussion-lessons-migration/LSN-0022-pbs-globals-lifecycle-and-published-entrypoint-legacy.md","status":"done","created_at":"2026-03-27","updated_at":"2026-03-27"}]} +{"type":"discussion","id":"DSC-0008","status":"done","ticket":"pbs-low-level-asset-manager-surface","title":"PBS Low-Level Asset Manager Surface for Runtime AssetManager","created_at":"2026-03-27","updated_at":"2026-03-27","tags":["compiler","pbs","runtime","asset-manager","host-abi","stdlib","asset"],"agendas":[],"decisions":[],"plans":[],"lessons":[{"id":"LSN-0023","file":"discussion/lessons/DSC-0008-pbs-low-level-asset-manager-surface/LSN-0023-lowassets-runtime-aligned-sdk-surface.md","status":"done","created_at":"2026-03-27","updated_at":"2026-03-27"}]} +{"type":"discussion","id":"DSC-0009","status":"done","ticket":"studio-debugger-workspace-integration","title":"Integrate ../debugger into Studio as a dedicated workspace","created_at":"2026-03-30","updated_at":"2026-04-07","tags":["studio","debugger","workspace","integration","shell"],"agendas":[],"decisions":[],"plans":[],"lessons":[]} +{"type":"discussion","id":"DSC-0010","status":"done","ticket":"studio-code-editor-workspace-foundations","title":"Establish Code Editor workspace foundations in Studio without LSP","created_at":"2026-03-30","updated_at":"2026-03-31","tags":["studio","editor","workspace","multi-frontend","lsp-deferred"],"agendas":[],"decisions":[],"plans":[],"lessons":[{"id":"LSN-0026","file":"discussion/lessons/DSC-0010-studio-code-editor-workspace-foundations/LSN-0026-read-only-editor-foundations-and-semantic-deferral.md","status":"done","created_at":"2026-03-31","updated_at":"2026-03-31"}]} +{"type":"discussion","id":"DSC-0011","status":"done","ticket":"compiler-analyze-compile-build-pipeline-split","title":"Split compiler pipeline into analyze, compile, and build entrypoints","created_at":"2026-03-30","updated_at":"2026-03-30","tags":["compiler","pipeline","artifacts","build","analysis"],"agendas":[],"decisions":[],"plans":[],"lessons":[{"id":"LSN-0025","file":"discussion/lessons/DSC-0011-compiler-analyze-compile-build-pipeline-split/LSN-0025-compiler-pipeline-entrypoints-and-result-boundaries.md","status":"done","created_at":"2026-03-30","updated_at":"2026-03-30"}]} +{"type":"discussion","id":"DSC-0012","status":"done","ticket":"studio-editor-document-vfs-boundary","title":"Definir um boundary de VFS documental para tree/view/open files no Code Editor do Studio","created_at":"2026-03-31","updated_at":"2026-03-31","tags":["studio","editor","workspace","vfs","filesystem","boundary"],"agendas":[],"decisions":[],"plans":[],"lessons":[{"id":"LSN-0027","file":"discussion/lessons/DSC-0012-studio-editor-document-vfs-boundary/LSN-0027-project-document-vfs-and-session-owned-editor-boundary.md","status":"done","created_at":"2026-03-31","updated_at":"2026-03-31"}]} +{"type":"discussion","id":"DSC-0013","status":"done","ticket":"studio-editor-write-wave-supported-non-frontend-files","title":"Definir a wave inicial de edicao no Code Editor apenas para arquivos aceitos e nao relacionados ao FE","created_at":"2026-03-31","updated_at":"2026-04-02","tags":["studio","editor","workspace","write","read-only","vfs","frontend-boundary"],"agendas":[],"decisions":[],"plans":[],"lessons":[{"id":"LSN-0028","file":"discussion/lessons/DSC-0013-studio-editor-write-wave-supported-non-frontend-files/LSN-0028-controlled-editor-write-wave-and-read-only-frontend-semantic-phase.md","status":"done","created_at":"2026-04-02","updated_at":"2026-04-02"}]} +{"type":"discussion","id":"DSC-0014","status":"done","ticket":"studio-frontend-owned-semantic-editor-presentation","title":"Definir ownership do schema visual semantico do editor por frontend","created_at":"2026-04-02","updated_at":"2026-04-02","tags":["studio","editor","frontend","presentation","semantic-highlighting","compiler","pbs"],"agendas":[],"decisions":[],"plans":[],"lessons":[{"id":"LSN-0029","file":"discussion/lessons/DSC-0014-studio-frontend-owned-semantic-editor-presentation/LSN-0029-frontend-owned-semantic-presentation-descriptor-and-host-consumption.md","status":"done","created_at":"2026-04-02","updated_at":"2026-04-02"}]} +{"type":"discussion","id":"DSC-0015","status":"done","ticket":"pbs-service-facade-reserved-metadata","title":"SDK Service Bodies Calling Builtin/Intrinsic Proxies as Ordinary PBS Code","created_at":"2026-04-03","updated_at":"2026-04-03","tags":["compiler","pbs","sdk","stdlib","lowering","service","intrinsic","sdk-interface"],"agendas":[],"decisions":[],"plans":[],"lessons":[{"id":"LSN-0030","file":"discussion/lessons/DSC-0015-pbs-service-facade-reserved-metadata/LSN-0030-sdk-service-bodies-over-private-reserved-proxies.md","status":"done","created_at":"2026-04-03","updated_at":"2026-04-03"}]} +{"type":"discussion","id":"DSC-0016","status":"done","ticket":"studio-editor-scope-guides-and-brace-anchoring","title":"Scope Guides do Code Editor com ancoragem exata em braces e destaque do escopo ativo","created_at":"2026-04-03","updated_at":"2026-04-06","tags":["studio","editor","scope-guides","braces","semantic-read","frontend-contract"],"agendas":[],"decisions":[],"plans":[],"lessons":[{"id":"LSN-0034","file":"discussion/lessons/DSC-0016-studio-editor-scope-guides-and-brace-anchoring/LSN-0034-active-scope-gutter-and-frontend-owned-structural-anchors.md","status":"done","created_at":"2026-04-06","updated_at":"2026-04-06"}]} +{"type":"discussion","id":"DSC-0017","status":"done","ticket":"studio-editor-inline-type-hints-for-let-bindings","title":"Inline Type Hints for Let Bindings in the Studio Editor","created_at":"2026-04-03","updated_at":"2026-04-06","tags":["studio","editor","inline-hints","inlay-hints","lsp","pbs","type-inference"],"agendas":[],"decisions":[],"plans":[],"lessons":[{"id":"LSN-0035","file":"discussion/lessons/DSC-0017-studio-editor-inline-type-hints-for-let-bindings/LSN-0035-frontend-owned-inline-hints-with-decorative-inline-rendering.md","status":"done","created_at":"2026-04-06","updated_at":"2026-04-06"}]} +{"type":"discussion","id":"DSC-0018","status":"done","ticket":"studio-project-local-studio-state-under-dot-studio","title":"Persist project-local Studio state under .studio","created_at":"2026-04-04","updated_at":"2026-04-04","tags":["studio","project-session","project-state","persistence","dot-studio","shell","layout","setup"],"agendas":[],"decisions":[],"plans":[],"lessons":[{"id":"LSN-0031","file":"discussion/lessons/DSC-0018-studio-project-local-studio-state-under-dot-studio/LSN-0031-project-local-studio-state-and-lifecycle-safe-layout-restoration.md","status":"done","created_at":"2026-04-04","updated_at":"2026-04-04"}]} +{"type":"discussion","id":"DSC-0019","status":"done","ticket":"studio-project-local-setup-separate-from-main-studio-state","title":"Separate project-local setup from the main Studio state under .studio","created_at":"2026-04-04","updated_at":"2026-04-04","tags":["studio","project-session","project-state","persistence","dot-studio","setup","boundary"],"agendas":[],"decisions":[],"plans":[],"lessons":[{"id":"LSN-0032","file":"discussion/lessons/DSC-0019-studio-project-local-setup-separate-from-main-studio-state/LSN-0032-separate-project-config-from-session-restoration-state.md","status":"done","created_at":"2026-04-04","updated_at":"2026-04-04"}]} +{"type":"discussion","id":"DSC-0020","status":"done","ticket":"studio-editor-indentation-policy-and-project-setup","title":"Indentation Policy, Status-Bar Semantics, and Project-Local Editor Setup","created_at":"2026-04-04","updated_at":"2026-04-04","tags":["studio","editor","indentation","tabs","setup","dot-studio","configuration","ux"],"agendas":[],"decisions":[],"plans":[],"lessons":[{"id":"LSN-0033","file":"discussion/lessons/DSC-0020-studio-editor-indentation-policy-and-project-setup/LSN-0033-setup-owned-indentation-policy-and-project-bootstrap-defaults.md","status":"done","created_at":"2026-04-04","updated_at":"2026-04-04"}]} +{"type":"discussion","id":"DSC-0021","status":"done","ticket":"studio-frontend-editor-write-and-save-wave","title":"Enable Frontend Editing and Save in the Studio Code Editor","created_at":"2026-04-04","updated_at":"2026-04-06","tags":["studio","editor","frontend","write","save","vfs","lsp","pbs","access-policy"],"agendas":[],"decisions":[],"plans":[],"lessons":[{"id":"LSN-0036","file":"discussion/lessons/DSC-0021-studio-frontend-editor-write-and-save-wave/LSN-0036-vfs-owned-frontend-edit-and-save-wave.md","status":"done","created_at":"2026-04-06","updated_at":"2026-04-06"}]} +{"type":"discussion","id":"DSC-0022","status":"done","ticket":"studio-play-stop-cartridge-flow","title":"Wire the Studio Play/Stop button to shipper phase 1 cartridge preparation and runtime execution","created_at":"2026-04-06","updated_at":"2026-04-07","tags":["studio","play-stop","shipper","runtime","cartridge","shell"],"agendas":[],"decisions":[],"plans":[],"lessons":[{"id":"LSN-0043","file":"discussion/lessons/DSC-0022-studio-play-stop-and-debugger-integration/LSN-0043-studio-play-stop-and-debugger-integration.md","status":"done","created_at":"2026-04-07","updated_at":"2026-04-07"}]} +{"type":"discussion","id":"DSC-0023","status":"done","ticket":"gradle-version-catalog-migration","title":"Move dependency version management to Version Catalog (TOML)","created_at":"2026-04-07","updated_at":"2026-04-07","tags":["gradle","buildSrc","dependency-management","version-catalog"],"agendas":[],"decisions":[],"plans":[],"lessons":[{"id":"LSN-0037","file":"discussion/lessons/DSC-0023-gradle-version-catalog-migration/LSN-0037-gradle-version-catalog-adoption.md","status":"done","created_at":"2026-04-07","updated_at":"2026-04-07"}]} diff --git a/discussion/index.ndjson b/discussion/index.ndjson index b88da099..67ad4756 100644 --- a/discussion/index.ndjson +++ b/discussion/index.ndjson @@ -1,8 +1,8 @@ -{"type":"meta","next_id":{"DSC":35,"AGD":38,"DEC":35,"PLN":75,"LSN":49,"CLSN":1}} +{"type":"meta","next_id":{"DSC":35,"AGD":38,"DEC":35,"PLN":75,"LSN":51,"CLSN":1}} {"type":"discussion","id":"DSC-0034","status":"done","ticket":"frontend-semantic-host-projection-flexibility","title":"Frontend semantic vocabulary flexibility and declarative host projection","created_at":"2026-05-06","updated_at":"2026-05-07","tags":["compiler","compiler-general","frontend","semantics","vscode","host-projection","lsp"],"agendas":[],"decisions":[],"plans":[],"lessons":[{"id":"LSN-0048","file":"discussion/lessons/DSC-0034-frontend-semantic-host-projection-flexibility/LSN-0048-frontend-owned-semantic-vocabularies-with-declarative-host-projection.md","status":"done","created_at":"2026-05-07","updated_at":"2026-05-07"}]} -{"type":"discussion","id":"DSC-0033","status":"in_progress","ticket":"frontend-visual-theme-spec-and-css-retirement","title":"Frontend visual theme spec and retirement of host-consumed semantic CSS","created_at":"2026-05-06","updated_at":"2026-05-06","tags":["compiler","compiler-general","frontend","presentation","theming","studio","vscode","lsp","pbs"],"agendas":[{"id":"AGD-0036","file":"AGD-0036-frontend-visual-theme-spec-and-css-retirement.md","status":"accepted","created_at":"2026-05-06","updated_at":"2026-05-06"}],"decisions":[{"id":"DEC-0033","file":"DEC-0033-frontend-visual-theme-spec-and-css-retirement.md","status":"accepted","created_at":"2026-05-06","updated_at":"2026-05-06","ref_agenda":"AGD-0036"}],"plans":[{"id":"PLN-0068","file":"PLN-0068-frontend-visual-contract-and-pbs-migration.md","status":"open","created_at":"2026-05-06","updated_at":"2026-05-06","ref_decisions":["DEC-0033"]},{"id":"PLN-0069","file":"PLN-0069-lsp-visual-theme-transport-and-selection.md","status":"open","created_at":"2026-05-06","updated_at":"2026-05-06","ref_decisions":["DEC-0033"]},{"id":"PLN-0070","file":"PLN-0070-studio-visual-theme-adapter-and-css-retirement.md","status":"open","created_at":"2026-05-06","updated_at":"2026-05-06","ref_decisions":["DEC-0033"]},{"id":"PLN-0071","file":"PLN-0071-vscode-dynamic-theme-translation-adapter.md","status":"open","created_at":"2026-05-06","updated_at":"2026-05-06","ref_decisions":["DEC-0033"]}],"lessons":[]} +{"type":"discussion","id":"DSC-0033","status":"done","ticket":"frontend-visual-theme-spec-and-css-retirement","title":"Frontend visual theme spec and retirement of host-consumed semantic CSS","created_at":"2026-05-06","updated_at":"2026-05-08","tags":["compiler","compiler-general","frontend","presentation","theming","studio","vscode","lsp","pbs"],"agendas":[],"decisions":[],"plans":[],"lessons":[{"id":"LSN-0050","file":"discussion/lessons/DSC-0033-frontend-visual-theme-spec-and-css-retirement/LSN-0050-frontend-owned-visual-themes-with-structured-contract-and-host-adapters.md","status":"done","created_at":"2026-05-08","updated_at":"2026-05-08"}]} {"type":"discussion","id":"DSC-0032","status":"done","ticket":"studio-new-lsp-api-and-v1-boundary","title":"Novo boundary entre lsp-api, lsp-v1 e a extensao VS Code","created_at":"2026-05-05","updated_at":"2026-05-07","tags":["studio","lsp","vscode","protocol","api","boundary"],"agendas":[],"decisions":[],"plans":[],"lessons":[{"id":"LSN-0047","file":"discussion/lessons/DSC-0032-studio-new-lsp-api-and-v1-boundary/LSN-0047-project-scoped-lsp-boundary-and-protocol-containment.md","status":"done","created_at":"2026-05-07","updated_at":"2026-05-07"}]} -{"type":"discussion","id":"DSC-0031","status":"in_progress","ticket":"studio-editor-workspace-cleanup","title":"Limpeza completa do Workspace Editor do Studio e remoção dos acoplamentos legados","created_at":"2026-05-05","updated_at":"2026-05-05","tags":["studio","editor","cleanup","vfs","lsp","migration"],"agendas":[{"id":"AGD-0034","file":"AGD-0034-vscode-editor-migration-feasibility.md","status":"accepted","created_at":"2026-05-05","updated_at":"2026-05-05"}],"decisions":[{"id":"DEC-0031","file":"DEC-0031-studio-editor-workspace-cleanup.md","status":"in_progress","created_at":"2026-05-05","updated_at":"2026-05-05","ref_agenda":"AGD-0034"}],"plans":[{"id":"PLN-0062","file":"PLN-0062-shell-session-and-state-cleanup-after-editor-removal.md","status":"done","created_at":"2026-05-05","updated_at":"2026-05-05","ref_decisions":["DEC-0031"]},{"id":"PLN-0063","file":"PLN-0063-legacy-lsp-and-vfs-module-removal-with-runtime-preservation.md","status":"done","created_at":"2026-05-05","updated_at":"2026-05-05","ref_decisions":["DEC-0031"]},{"id":"PLN-0064","file":"PLN-0064-normative-test-and-lesson-cleanup-for-editor-stack-removal.md","status":"done","created_at":"2026-05-05","updated_at":"2026-05-05","ref_decisions":["DEC-0031"]}],"lessons":[]} +{"type":"discussion","id":"DSC-0031","status":"done","ticket":"studio-editor-workspace-cleanup","title":"Limpeza completa do Workspace Editor do Studio e remoção dos acoplamentos legados","created_at":"2026-05-05","updated_at":"2026-05-08","tags":["studio","editor","cleanup","vfs","lsp","migration"],"agendas":[],"decisions":[],"plans":[],"lessons":[{"id":"LSN-0049","file":"discussion/lessons/DSC-0031-studio-editor-workspace-cleanup/LSN-0049-remove-the-embedded-editor-stack-before-rebuilding-code-workflows.md","status":"done","created_at":"2026-05-08","updated_at":"2026-05-08"}]} {"type":"discussion","id":"DSC-0030","status":"done","ticket":"studio-scene-pack-runtime-binary-contract","title":"Studio scene pack contract for runtime SCENE binary payload","created_at":"2026-04-24","updated_at":"2026-05-01","tags":["studio","packer","runtime","scene","asset-pack","binary-format","tiled"],"agendas":[],"decisions":[],"plans":[],"lessons":[{"id":"LSN-0046","file":"discussion/lessons/DSC-0030-studio-scene-pack-runtime-binary-contract/LSN-0046-canonical-scene-owns-editorial-truth-while-pack-stays-request-driven.md","status":"done","created_at":"2026-05-01","updated_at":"2026-05-01"}]} {"type":"discussion","id":"DSC-0029","status":"done","ticket":"studio-frame-composer-syscall-and-sprite-alignment","title":"Studio Alignment with Runtime FrameComposer Syscalls and Sprite Composition","created_at":"2026-04-18","updated_at":"2026-04-18","tags":["studio","compiler","pbs","stdlib","runtime-alignment","abi","syscall","frame-composer","sprites"],"agendas":[],"decisions":[],"plans":[],"lessons":[{"id":"LSN-0041","file":"discussion/lessons/DSC-0029-studio-frame-composer-syscall-and-sprite-alignment/LSN-0041-composer-must-own-public-sprite-composition.md","status":"done","created_at":"2026-04-18","updated_at":"2026-04-18"}]} {"type":"discussion","id":"DSC-0028","status":"done","ticket":"studio-tiled-parser-assets-scene-asset-type","title":"Tiled Parser and Scene Asset-Type Ownership in Assets Workspace","created_at":"2026-04-15","updated_at":"2026-04-23","tags":["studio","assets","scene","tiled","parser","asset-type"],"agendas":[],"decisions":[],"plans":[],"lessons":[{"id":"LSN-0045","file":"discussion/lessons/DSC-0028-studio-tiled-parser-assets-scene-asset-type/LSN-0045-asset-owned-scene-bank-and-tiled-xml-workflow.md","status":"done","created_at":"2026-04-23","updated_at":"2026-04-23"}]} diff --git a/discussion/lessons/DSC-0031-studio-editor-workspace-cleanup/LSN-0049-remove-the-embedded-editor-stack-before-rebuilding-code-workflows.md b/discussion/lessons/DSC-0031-studio-editor-workspace-cleanup/LSN-0049-remove-the-embedded-editor-stack-before-rebuilding-code-workflows.md new file mode 100644 index 00000000..f43682a2 --- /dev/null +++ b/discussion/lessons/DSC-0031-studio-editor-workspace-cleanup/LSN-0049-remove-the-embedded-editor-stack-before-rebuilding-code-workflows.md @@ -0,0 +1,84 @@ +--- +id: LSN-0049 +discussion: DSC-0031 +title: Remove the embedded editor stack before rebuilding code workflows +status: done +created: 2026-05-08 +updated: 2026-05-08 +tags: [studio, editor, cleanup, lsp, vfs, shell, migration] +--- + +## Original Problem + +Studio still carried an embedded `Code Editor` workspace together with a `prometeu-vfs` boundary and a legacy `prometeu-lsp` path that existed only to support that editor. + +That stack had become architectural drag: + +- the JavaFX editor was no longer a product direction; +- the legacy `VFS` and `LSP` contracts were shaped around that editor model; +- shell state and project session still persisted editor-specific assumptions; +- and keeping those surfaces alive made any future code-backend redesign harder. + +## Consolidated Decision + +`DEC-0031` locked a full cleanup of the embedded editor stack. + +The repository removed: + +- the `Code Editor` workspace as an active Studio surface; +- the legacy editor-owned `VFS` boundary; +- the legacy editor-era `LSP` assumptions; +- shell/session/state dependencies that expected the editor to exist; +- and normative references that treated that stack as current architecture. + +The decision also locked an equally important limit: + +- this cleanup was not allowed to define the future code backend; +- a replacement LSP or automation boundary had to come later, in separate discussion. + +## Final Result + +The Studio shell now opens with surviving workspaces only: `Assets`, `Debug`, and `Shipper`. + +Project-local state no longer persists editor restoration or editor layout fields, while still loading old state safely and falling back to surviving shell behavior. + +The cleanup also succeeded without freezing the repository in a "no LSP ever again" state. +Later work in `DSC-0032` introduced a new project-scoped LSP boundary as separate architecture, which is exactly what `DEC-0031` required: remove the old stack first, then rebuild cleanly under a new decision. + +## Implementation Notes + +The cleanup landed in three coordinated waves: + +1. shell/session/state cleanup removed `WorkspaceId.EDITOR`, editor restoration state, and editor-owned session composition; +2. the old editor-era `VFS` and `LSP` stack stopped being the active Studio foundation; +3. specs, tests, and historical references were revised so the removed editor stack no longer appears as current product guidance. + +This produced an important boundary reset: + +- Studio remains responsible for launcher, assets, shipper, debug, build, and run orchestration; +- code-editing architecture is no longer smuggled in through dead UI or legacy session seams. + +## Example + +Before the cleanup, an old `.studio/state.json` could still restore editor-centric state. + +After the cleanup, the same persisted payload is treated defensively: + +- old editor fields are ignored; +- the selected workspace falls back safely when `EDITOR` is present; +- the project reopens into a surviving workspace instead of reviving a dead surface. + +## Pitfalls and Anti-Patterns + +- Do not preserve dead editor-era boundaries "for compatibility" when the product direction has already moved. +- Do not treat naming continuity as architectural continuity. A later `prometeu-lsp` module can be valid if it comes from a new discussion and a new boundary. +- Do not leave project-local state as an accidental migration trap; persisted legacy fields must degrade safely. + +## References + +- `AGD-0034` Limpeza completa do Workspace Editor do Studio e remoção dos acoplamentos legados +- `DEC-0031` Limpeza completa do Workspace Editor do Studio e remoção dos acoplamentos legados +- `PLN-0062` Shell Session and State Cleanup After Editor Removal +- `PLN-0063` Legacy LSP and VFS Module Removal with Runtime Preservation +- `PLN-0064` Normative Test and Lesson Cleanup for Editor Stack Removal +- `LSN-0047` Project-scoped LSP boundary and protocol containment diff --git a/discussion/lessons/DSC-0033-frontend-visual-theme-spec-and-css-retirement/LSN-0050-frontend-owned-visual-themes-with-structured-contract-and-host-adapters.md b/discussion/lessons/DSC-0033-frontend-visual-theme-spec-and-css-retirement/LSN-0050-frontend-owned-visual-themes-with-structured-contract-and-host-adapters.md new file mode 100644 index 00000000..67fd8eca --- /dev/null +++ b/discussion/lessons/DSC-0033-frontend-visual-theme-spec-and-css-retirement/LSN-0050-frontend-owned-visual-themes-with-structured-contract-and-host-adapters.md @@ -0,0 +1,93 @@ +--- +id: LSN-0050 +discussion: DSC-0033 +title: Frontend-owned visual themes with structured contract and host adapters +status: done +created: 2026-05-08 +updated: 2026-05-08 +tags: [compiler, compiler-general, frontend, presentation, theming, lsp, vscode, pbs] +--- + +## Original Problem + +Frontend semantic presentation was frontend-owned in principle, but not in a form that could survive multiple hosts. + +PBS still depended on authored semantic CSS as the practical visual source of truth, which created three problems: + +- CSS was a host-facing artifact rather than a compiler-general contract; +- VS Code could only approximate frontend intent through manual translation; +- every host risked drifting away from the frontend's real visual identity. + +## Consolidated Decision + +`DEC-0033` replaced authored host-consumed semantic CSS with a structured frontend-owned visual contract. + +That contract now owns: + +- the frontend theme list; +- the default active theme; +- token-scoped styles; +- editor-surface palette data; +- and host projections used to translate frontend semantic keys into host-native semantic selectors. + +Hosts are adapters over this data. +They do not own frontend visual truth. + +## Final Result + +The canonical visual source now lives in `FrontendSemanticPresentationSpec`, with concrete PBS theme data and host projections authored in structured Java models instead of CSS resources. + +The new LSP path transports: + +- frontend semantic keys; +- visual themes; +- active theme identity; +- and host projection metadata. + +The VS Code extension consumes that payload and writes semantic token and workbench color customizations dynamically, which means routine frontend color changes no longer require hand-edited extension theme tables. + +The old PBS semantic CSS still exists only as migration residue and derivative compatibility material. +It is no longer the authored canonical contract. + +## Implementation Notes + +The decision was realized across four layers: + +1. compiler/frontend metadata grew a structured presentation contract; +2. PBS migrated its theme definition into that contract; +3. the LSP description path started exporting visual themes and host projections; +4. the VS Code extension became a mechanical translator of the contract at runtime. + +This also clarified the relationship between `DSC-0033` and `DSC-0034`: + +- `DSC-0033` established the structured theme contract and CSS retirement; +- `DSC-0034` established that host projections belong in the frontend contract rather than in the host. + +Together they define the current highlight pipeline. + +## Example + +For PBS today: + +- the frontend publishes semantic keys such as `pbs-keyword` and `pbs-service`; +- the same frontend publishes the canonical theme colors and emphasis flags for those keys; +- the LSP sends the theme plus a `vscode` host projection; +- the VS Code extension applies both the canonical semantic selectors and the projected host selectors. + +This is why a color change in PBS theme data can flow to VS Code without a new curated palette in `package.json`. + +## Pitfalls and Anti-Patterns + +- Do not reintroduce CSS as a silent second source of truth. +- Do not move frontend theme authorship into host adapters just because one host has capability gaps. +- Do not collapse frontend semantic identity into generic host categories during transport; host categories are projections, not the canonical vocabulary. + +## References + +- `AGD-0036` Frontend Visual Theme Spec and Retirement of Host-Consumed Semantic CSS +- `DEC-0033` Frontend-owned visual theme spec as canonical presentation contract +- `PLN-0068` Frontend Visual Contract and PBS Migration +- `PLN-0069` LSP Visual Theme Transport and Theme Selection Propagation +- `PLN-0070` Studio Visual Theme Adapter and CSS Retirement +- `PLN-0071` VS Code Dynamic Theme Translation Adapter +- `LSN-0048` Frontend-owned semantic vocabularies with declarative host projection diff --git a/discussion/workflow/agendas/AGD-0034-vscode-editor-migration-feasibility.md b/discussion/workflow/agendas/AGD-0034-vscode-editor-migration-feasibility.md deleted file mode 100644 index 79011aab..00000000 --- a/discussion/workflow/agendas/AGD-0034-vscode-editor-migration-feasibility.md +++ /dev/null @@ -1,106 +0,0 @@ ---- -id: AGD-0034 -ticket: studio-editor-workspace-cleanup -title: Limpeza completa do Workspace Editor do Studio e remoção dos acoplamentos legados -status: accepted -created: 2026-05-05 -resolved: 2026-05-05 -decision: DEC-0031 -tags: [studio, editor, cleanup, vfs, lsp, migration] ---- - -## Pain - -O repositório ainda carrega um `Workspace Editor` no `prometeu-studio` junto com camadas de `VFS` e `LSP` desenhadas especificamente para esse editor embutido. - -Esse conjunto virou um legado arquitetural: - -- o editor JavaFX não é mais a direção do produto; -- o `prometeu-vfs` atual está acoplado ao modelo editorial do editor embutido; -- o `prometeu-lsp` atual está acoplado ao `VFS` e ao host local do Studio; -- e manter essa base viva só aumenta o custo da futura reconstrução correta do backend de código. - -## Context - -- O monorepo já separa `prometeu-compiler`, `prometeu-packer` e `prometeu-studio`, mas o `prometeu-lsp` e o `prometeu-vfs` atuais nasceram como suporte ao editor embutido. -- A capacidade de compilação dos projetos deve continuar existindo no Studio. -- O alvo imediato não é discutir o novo LSP nem o novo contrato de automação. -- O alvo imediato é remover: - - o `Workspace Editor`; - - o `prometeu-lsp` legado usado por ele; - - e o `prometeu-vfs` acoplado a esse modelo editorial. -- O Studio continua existindo como produto fora do editor: - - shell e launcher de projeto; - - assets workspace; - - shipper/build surfaces; - - play/stop e integração com runtime/debug. -- Uma agenda futura poderá discutir a reconstrução do backend de código e do novo servidor LSP, mas isso fica fora deste artefato. - -## Open Questions - -- Quais partes do `prometeu-vfs` atual pertencem exclusivamente ao `Workspace Editor` e podem ser removidas integralmente? -- Existe algum consumer ainda válido do `prometeu-lsp` legado fora do editor embutido? -- O fluxo `play` ou qualquer outro fluxo do Studio depende hoje, mesmo indiretamente, de APIs do editor legado, do `VFS` legado ou do `LSP` legado? -- A limpeza deve remover apenas código de produção ou também specs, testes, lessons e referências que tratam o editor embutido como superfície ativa? -- Quais contratos de compilação precisam ser preservados explicitamente enquanto a camada de edição é removida? - -## Options - -### Option A - Manter o editor legado até a reconstrução completa do backend de código -- **Approach:** adiar a limpeza e preservar temporariamente `Workspace Editor`, `prometeu-vfs` legado e `prometeu-lsp` legado até o novo backend existir. -- **Pro:** menor ruptura imediata. -- **Con:** prolonga a vida do legado, aumenta custo de manutenção e deixa a futura reconstrução mais confusa. -- **Maintainability:** fraca. - -### Option B - Limpeza completa agora, preservando apenas a compilação do Studio -- **Approach:** remover `Workspace Editor`, `prometeu-lsp` legado e o `prometeu-vfs` acoplado a esse modelo, mantendo apenas as superfícies de compilação e execução que não dependem desse stack. -- **Pro:** reduz o legado antes da reconstrução, clarifica boundaries e impede que o futuro LSP nasça comprometido por compatibilidade acidental. -- **Con:** cria um período sem editor embutido e sem backend de código novo dentro do Studio. -- **Maintainability:** forte. - -Vamos de Option B. - -## Discussion - -O trabalho desta agenda não é desenhar o novo backend de código. - -O trabalho desta agenda é remover o legado que impediria esse redesenho. - -Isso implica alguns cortes diretos: - -- o `Workspace Editor` deixa de ser superfície ativa do Studio; -- o `prometeu-lsp` atual deixa de ser tratado como base evolutiva; -- o `prometeu-vfs` atual, por ser acoplado ao modelo editorial do editor embutido, sai junto com esse stack; -- as capacidades de compilação, build e execução que não dependem desse stack devem ser preservadas. - -O princípio aqui é de limpeza arquitetural antes de reconstrução: - -- não carregar compatibilidade acidental com o editor antigo; -- não manter um `VFS` ou `LSP` cujo contrato nasce de um modelo que já foi abandonado; -- e não misturar, nesta discussão, a limpeza do legado com o desenho do futuro servidor LSP. - -Isso também reduz o risco de falsa migração: - -- em vez de adaptar o editor atual, o repositório assume explicitamente que ele vai morrer; -- em vez de reaproveitar um `LSP` embrionário acoplado ao host local, o repositório aceita que um novo backend de código será desenhado depois; -- e em vez de preservar o `VFS` por inércia, o repositório valida se ele ainda possui valor fora do modelo que o originou. - -## Resolution - -Recomendação preliminar: - -- seguir com a Option B; -- tratar esta agenda exclusivamente como limpeza completa do `Workspace Editor` do Studio; -- remover junto o `prometeu-lsp` legado e o `prometeu-vfs` acoplado a esse modelo; -- preservar explicitamente a capacidade de compilação e os fluxos do Studio que não dependem desse stack; -- e abrir uma discussão futura separada para o backend de código novo, o novo LSP e o contrato de automação. - -## Next Step - -Se a direção fizer sentido, o próximo passo disciplinado é fechar uma `decision` com: - -1. o escopo exato da remoção do `Workspace Editor`; -2. o escopo exato da remoção do `prometeu-lsp` legado; -3. o escopo exato da remoção do `prometeu-vfs` acoplado a esse modelo; -4. as capacidades de compilação e execução que devem sobreviver intactas; -5. e os artefatos normativos, testes e código que precisam ser limpos ou preservados. diff --git a/discussion/workflow/agendas/AGD-0036-frontend-visual-theme-spec-and-css-retirement.md b/discussion/workflow/agendas/AGD-0036-frontend-visual-theme-spec-and-css-retirement.md deleted file mode 100644 index ee9a3863..00000000 --- a/discussion/workflow/agendas/AGD-0036-frontend-visual-theme-spec-and-css-retirement.md +++ /dev/null @@ -1,147 +0,0 @@ ---- -id: AGD-0036 -ticket: frontend-visual-theme-spec-and-css-retirement -title: Frontend Visual Theme Spec and Retirement of Host-Consumed Semantic CSS -status: accepted -created: 2026-05-06 -resolved: 2026-05-06 -decision: DEC-0033 -tags: [compiler, compiler-general, frontend, presentation, theming, studio, vscode, lsp, pbs] ---- - -## Pain - -The current semantic highlighting path is no longer strong enough now that Prometeu must project frontend-owned presentation into more than one host. - -Today the frontend still effectively ships a host-facing CSS file as the practical source of truth for visual presentation. -That works tolerably for the legacy Studio editor path, but it collapses once the same frontend presentation must be exported to VS Code through LSP semantic tokens. - -The result is a weak cross-host contract: - -- the frontend publishes semantic keys, but not a complete visual spec, -- `semantic-highlighting.css` still acts as the real authored presentation artifact, -- VS Code only receives a partial hand-translated approximation, -- and each host risks drifting away from the frontend's intended visual identity. - -The CSS file should be treated as migration input only and must die by the end of this refactor. - -## Context - -Domain owner: `compiler/general` - -Propagation targets are expected in at least three places: - -- compiler frontend metadata and contracts, -- Studio host consumption, -- VS Code extension host consumption. - -Relevant historical context already exists in `LSN-0029`, which established frontend ownership of semantic presentation metadata through `FrontendSpec`. -That lesson is still useful for ownership boundaries, but it is not sufficient for the next wave because the current contract is too weak and too resource-oriented. - -Current state: - -- `FrontendSemanticPresentationSpec` exposes only `semanticKeys` and opaque `resources`, -- PBS publishes `/themes/pbs/semantic-highlighting.css` as a semantic presentation resource, -- Studio can consume that resource directly, -- VS Code cannot consume that CSS directly and must approximate it via `package.json` and semantic token theming, -- recent LSP work now transports PBS semantic token types, but the host-side rendering still falls short of the original PBS editor look. - -What is missing is a frontend-owned visual spec that is structured enough to be exported to multiple hosts without making CSS the canonical source. - -## Open Questions - -- [x] What is the canonical replacement for `semantic-highlighting.css` inside `FrontendSpec`? - R: a structured visual presentation spec (a JSON) that includes semantic token styles and editor-level colors. -- [x] Which parts of frontend presentation are normative and cross-host, and which are host-specific adapters only? - R: a ideia eh que o FE presentation possa ser completamente expostado para os clientes como o VSCode. -- [x] Should the visual contract be semantic-token-centric only, or should it also include editor-level colors such as base foreground, selection, gutter, and accent surfaces? - R: o contrato visual pode ofertar toda essa gama de atributos para cada token, o cliente (VSCode) pode usa-los para compor o tema, mas o contrato deve ser token-centric para garantir que a intenção visual seja sempre atrelada a chaves semânticas. -- [x] How should Studio consume the new visual spec without keeping CSS as a hidden canonical source? - R: o FE Presentation na medida que o servidor eh described oferece um contrato visual estruturado, o cliente (VSCode extension) deve consumir esse contrato e gerar o que tiver que gerar para compor o tema. Se o cliente usar CSS que gere isso. -- [x] How should VS Code consume the new visual spec: static generated contribution, runtime translation, or both? - R: A ideia eh que o cliente seja bem burro, ele deve ser uma maquina que traduz o contrato visual para um formato que o VSCode entenda, seja isso um contribution estatico ou uma tradução dinamica, o importante eh que o contrato visual seja o unico input e a fonte de verdade para a intencao visual do frontend. -- [x] How do we phase out existing frontend-owned CSS resources without breaking current Studio rendering during migration? - R: nada no studio depende desse CSS, ele eh um artefato de migração para o PBS. O contrato visual deve ser definido e implementado no PBS primeiro, usando o CSS como input para derivar o formato estruturado. Depois disso, o CSS pode ser descontinuado. -- [x] How do we version and validate the visual contract so new frontends can implement it consistently? - R: o contrato deve viver dentro de `FrontendSpec` e ser versionado junto com ele. - -## Options - -### Option A - Keep CSS as the canonical frontend artifact and add exporters around it - -- **Approach:** Preserve `semantic-highlighting.css` as the frontend-owned source and build tooling that parses or translates it into Studio and VS Code outputs. -- **Pro:** Smallest migration cost in the short term, because PBS already has authored CSS. -- **Con:** Keeps host-facing CSS as the source of truth, which is the wrong abstraction for multi-host consumption and weak for validation. -- **Maintainability:** Poor. Every new host would need a CSS interpretation path or a CSS-to-host adapter with lossy translation rules. - -### Option B - Introduce a structured frontend visual spec and treat CSS as a temporary migration input - -- **Approach:** Replace the current resource-centric semantic presentation contract with a structured visual spec published by the frontend. Use the existing CSS only as bootstrap input while migrating PBS, then retire it as canonical data. -- **Pro:** Creates a real multi-host contract that can be exported mechanically to Studio and VS Code while preserving frontend ownership. -- **Con:** Requires contract design, adapter work in both hosts, and a migration story for current frontend resources. -- **Maintainability:** Strong. New frontends would author one canonical visual contract and hosts would implement stable adapters. - -### Option C - Split the contract into semantic vocabulary plus host-owned themes - -- **Approach:** Keep frontend ownership only over semantic keys and let each host define its own visual theme for those keys. -- **Pro:** Simplifies frontend metadata and gives each host more freedom. -- **Con:** Reintroduces host ownership over frontend meaning in practice and guarantees visual drift between Studio and VS Code. -- **Maintainability:** Medium at best. It reduces frontend burden but loses the core requirement of frontend-owned identity. - -## Tradeoffs - -Option A looks attractive because it reuses existing assets, but it cements the wrong boundary. -If CSS remains canonical, the compiler/frontend layer still cannot describe its own presentation in a host-neutral way. - -Option C is cleaner than the current situation from a tooling perspective, but it fails the product goal. -The user experience would vary per host because visual meaning would no longer be frontend-owned. - -Option B is the only direction that preserves the previous ownership decision while extending it into a credible cross-host architecture. -Its cost is real, but that cost is exactly the work we need to make the contract durable. - -## Recommendation - -Adopt Option B. - -The frontend should publish a structured visual presentation spec as canonical data. -That spec should become the only normative source for frontend semantic/editor appearance that is intended to survive across hosts. - -`semantic-highlighting.css` should be used only as migration input for PBS while we derive the first structured visual spec. -After migration, CSS may remain as a generated Studio adapter artifact for a while, but it must no longer be treated as authored truth. - -The new contract likely needs at least these conceptual layers: - -- semantic token styles, -- editor surface colors, -- optional UI accent colors tied to the editing surface, -- explicit host adapter boundaries. - -The LSP path should transport structured visual data or enough structured metadata for the VS Code extension to render the same frontend-owned intent without reverse-engineering CSS. - -## Discussion - -This agenda is intentionally narrower than “general editor theming”. -The problem is not to invent a universal Prometeu theme engine first. -The problem is to stop using frontend-authored CSS as the canonical semantic/editor presentation contract and replace it with a frontend-owned visual spec that survives host translation. - -The most important discipline point is ownership: - -- compiler/frontend owns semantic and visual intent, -- LSP transports frontend-owned intent, -- Studio and VS Code are rendering adapters, -- host adapters may have capability gaps, but they must not become canonical. - -There is also an important migration constraint: - -- PBS is the first frontend and will define the initial shape, -- but the contract must not become “PBS-specific metadata with generic naming later”, -- instead it must be valid as a compiler-general surface that PBS implements first. - -## Resolution - -Accepted on 2026-05-06. - -The discussion resolves in favor of a structured frontend-owned visual theme specification with support for multiple themes per frontend. -Themes remain tied to the frontend's own semantic vocabulary. -Studio and the VS Code extension act as adapters over that contract. -`semantic-highlighting.css` remains migration input only and must be retired as canonical authored truth. diff --git a/discussion/workflow/decisions/DEC-0031-studio-editor-workspace-cleanup.md b/discussion/workflow/decisions/DEC-0031-studio-editor-workspace-cleanup.md deleted file mode 100644 index 44777193..00000000 --- a/discussion/workflow/decisions/DEC-0031-studio-editor-workspace-cleanup.md +++ /dev/null @@ -1,148 +0,0 @@ ---- -id: DEC-0031 -ticket: studio-editor-workspace-cleanup -title: Limpeza completa do Workspace Editor do Studio e remoção dos acoplamentos legados -status: in_progress -created: 2026-05-05 -accepted: 2026-05-05 -agenda: AGD-0034 -plans: [PLN-0062, PLN-0063, PLN-0064] -tags: [studio, editor, cleanup, vfs, lsp, migration] ---- - -## Decision - -O repositório SHALL remover integralmente o `Workspace Editor` do Studio como superfície ativa do produto. - -Essa remoção SHALL incluir: - -1. o workspace de código embutido em `prometeu-studio`; -2. o `prometeu-lsp` legado usado por esse workspace; -3. o `prometeu-vfs` legado acoplado ao modelo editorial desse workspace; -4. os pontos de integração do shell, da sessão de projeto e do bootstrap que assumem a existência desse stack; -5. e os artefatos normativos, testes e referências documentais que tratam esse stack como superfície vigente. - -Ao mesmo tempo, esta decisão ALSO locks que: - -1. a capacidade de compilação dos projetos MUST permanecer disponível no Studio; -2. os fluxos atuais de `build`, `play`, `run` e `debug` MUST permanecer funcionais desde que não dependam do editor legado, do `prometeu-lsp` legado ou do `prometeu-vfs` legado; -3. esta decisão MUST NOT introduzir o novo backend de código, o novo servidor LSP ou o futuro contrato de automação; -4. qualquer reconstrução dessas superfícies MUST acontecer em discussão posterior e separada. - -## Rationale - -O `Workspace Editor`, o `prometeu-lsp` atual e o `prometeu-vfs` atual formam um stack único, criado especificamente para o editor embutido do Studio. - -Esse stack não é mais alinhado à direção do produto: - -1. o editor JavaFX deixou de ser a direção principal; -2. o `prometeu-lsp` atual não deve ser tratado como base séria para um futuro servidor LSP; -3. o `prometeu-vfs` atual carrega um contrato editorial pensado para o editor embutido; -4. manter esse legado vivo aumenta o custo de reconstrução e preserva boundaries errados por inércia. - -Portanto, a limpeza precisa acontecer antes da reconstrução. - -## Technical Specification - -### 1. Editor Workspace Removal - -O Studio MUST remover a superfície `Code Editor` do shell. - -Isso inclui: - -1. remover `WorkspaceId.EDITOR`; -2. remover o `EditorWorkspace` e todos os controles, painéis, modelos e helpers sob `prometeu-studio/.../workspaces/editor`; -3. remover a presença do editor na workspace rail, no layout principal e no fluxo de restauração de shell; -4. remover strings, ícones e estado visual exclusivos dessa superfície. - -### 2. Legacy LSP Removal - -O repositório MUST remover o `prometeu-lsp` legado como módulo ativo. - -Isso inclui: - -1. remover os módulos `prometeu-lsp-api` e `prometeu-lsp-v1`; -2. remover `LspService`, `LspServiceFactory` e todos os DTOs/messages específicos desse stack legado; -3. remover a criação e injeção dessas dependências no `AppContainer`, no `Container`, na sessão de projeto e nos testes associados; -4. remover a hipótese de que esse `LSP` será evoluído para o futuro backend de código. - -Os conceitos úteis descobertos nesse stack MAY ser reaproveitados mais tarde, mas esta decisão não preserva compatibilidade de código, pacote ou contrato com ele. - -### 3. Legacy VFS Removal - -O repositório MUST remover o `prometeu-vfs` legado como módulo ativo. - -Isso inclui: - -1. remover os módulos `prometeu-vfs-api` e `prometeu-vfs-v1`; -2. remover `VfsProjectDocument`, `ProjectDocumentVfsFactory` e implementações filesystem-backed associadas; -3. remover a criação e posse desse `VFS` na sessão de projeto; -4. remover qualquer regra que trate esse `VFS` como boundary documental vigente do Studio. - -Esta decisão assume que o `prometeu-vfs` atual pertence ao modelo do editor legado e, portanto, não deve sobreviver por compatibilidade acidental. - -### 4. Session and Shell Cleanup - -O Studio MUST reconfigurar a sessão de projeto e o shell principal para não depender do stack removido. - -Isso inclui: - -1. remover `LSP` e `VFS` legados da estrutura de `StudioProjectSession`; -2. remover sua criação em `StudioProjectSessionFactory`; -3. remover dependências globais correspondentes do bootstrap e do container; -4. remover persistência de layout e restauração editorial específicas do editor. - -### 5. State Cleanup - -O estado local do projeto MUST deixar de persistir dados exclusivos do editor legado. - -Isso inclui: - -1. remover `editorRestoration`; -2. remover `shellLayout.editorLayout`; -3. garantir fallback seguro para estados antigos já persistidos em `.studio/state.json`; -4. preservar apenas os campos ainda pertencentes a workspaces vivos e ao shell remanescente. - -### 6. Documentation and Test Cleanup - -O repositório MUST limpar artefatos normativos e testes que descrevem o stack legado como vigente. - -Isso inclui: - -1. revisar ou remover as specs do `Code Editor`, do `Project Document VFS` e do `Integrated LSP Semantic Read Phase`; -2. revisar `docs/specs/studio/README.md`; -3. remover ou arquivar testes exclusivos do editor, do `prometeu-lsp` legado e do `prometeu-vfs` legado; -4. revisar lessons e referências históricas para deixar explícito que se tratam de legado, quando forem mantidas. - -### 7. Capabilities That MUST Survive - -As seguintes capacidades MUST sobreviver a esta limpeza: - -1. compilação de projetos pelo pipeline canônico existente; -2. build de artefatos via `BuilderPipelineService`; -3. preparação do fluxo de shipper; -4. `play`, `run` e `debug` do Studio, desde que apoiados nas superfícies remanescentes e não no stack removido; -5. workspaces `Assets`, `Shipper` e `Debug`, além do launcher e do shell geral. - -### 8. Explicit Non-Goals - -Esta decisão MUST NOT: - -1. definir o novo servidor LSP; -2. definir o novo contrato de automação; -3. definir o novo modelo de sessão de código; -4. definir integração com VS Code; -5. reter compatibilidade com o `LSP` ou `VFS` legados por conveniência. - -## Constraints - -1. A limpeza MUST preservar o pipeline canônico `analyze`, `compile` e `build` já existente no compiler. -2. A limpeza MUST evitar remover ou degradar fluxos de `build/run/debug` que hoje dependem apenas de `compiler`, `shipper`, runtime e shell. -3. A limpeza MUST deixar o shell do Studio em estado coerente, sem workspace fantasma, sem layout órfão e sem dependências mortas. -4. A limpeza MUST tratar specs e estado persistido como parte do trabalho, não como detalhe pós-código. -5. A futura reconstrução do backend de código SHALL nascer em discussão separada, sem herdar obrigação de compatibilidade com o stack removido. - -## Revision Log - -- 2026-05-05: Initial draft from AGD-0034. -- 2026-05-05: Accepted and decomposed into PLN-0062, PLN-0063, and PLN-0064. diff --git a/discussion/workflow/decisions/DEC-0033-frontend-visual-theme-spec-and-css-retirement.md b/discussion/workflow/decisions/DEC-0033-frontend-visual-theme-spec-and-css-retirement.md deleted file mode 100644 index 77b9c876..00000000 --- a/discussion/workflow/decisions/DEC-0033-frontend-visual-theme-spec-and-css-retirement.md +++ /dev/null @@ -1,152 +0,0 @@ ---- -id: DEC-0033 -ticket: frontend-visual-theme-spec-and-css-retirement -title: Frontend-owned visual theme spec as canonical presentation contract -status: accepted -created: 2026-05-06 -accepted: 2026-05-06 -agenda: AGD-0036 -plans: [PLN-0068, PLN-0069, PLN-0070, PLN-0071] -tags: [compiler, compiler-general, frontend, presentation, theming, studio, vscode, lsp, pbs] ---- - -## Decision - -Prometeu SHALL replace frontend-authored host-consumed semantic CSS with a structured frontend-owned visual theme specification as the canonical presentation contract. - -This decision locks the following normative points: - -1. Each `FrontendSpec` MUST publish its own semantic vocabulary and MAY publish multiple visual themes for that vocabulary. -2. Visual themes MUST be frontend-owned and MUST remain associated with the semantic tokens defined by that same frontend. -3. `semantic-highlighting.css` MUST be treated as migration input only and MUST cease to be an authored canonical contract by the end of this refactor. -4. Studio and the VS Code extension MUST act as rendering adapters over the frontend-owned visual contract and MUST NOT become owners of frontend theme data. -5. The VS Code extension MUST translate the frontend visual contract dynamically or mechanically from the contract itself, so frontend visual adjustments do not require extension maintenance for each theme change. - -## Rationale - -The current model is structurally weak for multi-host consumption. -PBS still carries a CSS resource that works as the practical source of visual truth, while VS Code can only consume a partial manual approximation through semantic token configuration. - -That creates the wrong ownership boundary: - -1. the frontend owns semantic meaning but does not fully own its exported visual contract; -2. hosts are forced to reinterpret or approximate visual intent; -3. every frontend visual adjustment risks requiring host edits; -4. visual drift becomes likely across Studio and VS Code. - -The repository already established that semantic presentation belongs to the frontend. -This decision extends that ownership model into a stronger cross-host contract: - -1. the frontend authors semantic and visual intent once; -2. LSP transports that intent; -3. hosts adapt it without redefining it. - -## Technical Specification - -### 1. Canonical Visual Contract - -`FrontendSpec` MUST evolve to expose a structured visual presentation contract as canonical data. - -That contract MUST: - -1. live with the frontend definition; -2. be versioned together with `FrontendSpec`; -3. be sufficient for multiple hosts to render the frontend's intended appearance without interpreting CSS as the source of truth; -4. remain compiler-general even if PBS is the first frontend to implement it. - -The canonical contract MAY be encoded as JSON-backed structured data or as an equivalent strongly-typed model, but the authored source of truth MUST be the structured visual contract, not CSS. - -### 2. Frontend-Owned Themes - -Each frontend MAY publish multiple visual themes. - -Rules: - -1. themes MUST belong to the frontend that defines the semantic vocabulary they style; -2. themes MUST be expressed in terms of that frontend's own semantic token keys and related editor presentation surfaces; -3. hosts MAY select which frontend theme is active; -4. hosts MUST NOT redefine the theme contract as host-owned authored data. - -This means theme ownership is: - -1. frontend authors themes, -2. host selects and applies themes, -3. host does not author the frontend visual semantics. - -### 3. Token-Centric Contract with Editor Surfaces - -The visual contract MUST be token-centric, but it SHALL also support editor-level presentation data where needed to preserve frontend visual intent. - -Therefore the contract MUST be able to express: - -1. token-scoped presentation such as foreground, emphasis, and related token styling attributes; -2. editor surface colors such as base foreground, selection, gutter, and other editing-surface colors when they are part of frontend visual intent; -3. optional frontend-specific accents tied to the editing experience. - -Token-centricity remains mandatory because semantic meaning MUST stay anchored to semantic keys. -Editor-surface data is allowed because semantic fidelity alone is insufficient to reproduce frontend identity across hosts. - -### 4. Host Adapter Responsibilities - -Studio and the VS Code extension MUST consume the frontend visual contract as adapters. - -Studio: - -1. MUST consume the structured frontend visual contract; -2. MAY render through generated CSS or another host mechanism; -3. MUST NOT treat generated CSS as the canonical frontend artifact. - -VS Code extension: - -1. MUST consume the frontend visual contract through the server description path or an equivalent frontend-owned transport surface; -2. MUST translate that contract into whatever VS Code requires, whether through runtime translation, generated contributions, or another adapter mechanism; -3. MUST behave as a mechanical translator of the frontend contract; -4. MUST NOT require hand-maintained extension theme edits whenever a frontend changes a color, emphasis rule, or theme variant. - -### 5. LSP Transport Responsibilities - -The LSP path MUST transport enough structured frontend-owned visual information for hosts to render the active frontend theme. - -It MUST preserve: - -1. frontend identity, -2. semantic token identity, -3. theme identity where multiple themes exist, -4. visual attributes needed by the host adapter. - -LSP MUST NOT collapse frontend themes into host-authored generic theme categories. - -### 6. Migration and CSS Retirement - -`semantic-highlighting.css` is allowed only as migration input for the first structured contract derivation. - -Migration rules: - -1. PBS SHALL be the first frontend migrated; -2. the existing PBS CSS MAY be parsed or manually transcribed into the first canonical structured visual contract; -3. once the structured contract becomes authoritative, the CSS MUST no longer be treated as authored truth; -4. any remaining CSS after migration MAY exist only as generated adapter output or as temporary compatibility residue scheduled for removal; -5. the refactor is not complete while host-consumed semantic CSS remains the canonical frontend presentation source. - -### 7. Extension Stability Requirement - -This decision explicitly locks an operational requirement for `tools/vscode-extension`: - -1. frontend visual changes MUST be expressible by changing frontend-owned contract data; -2. such frontend changes MUST NOT force routine extension source edits; -3. the extension SHALL be stable as a contract adapter rather than a repository of manually curated frontend theme rules. - -## Constraints - -1. The canonical source of frontend visual intent MUST move out of authored CSS. -2. Theme ownership MUST remain with the frontend. -3. The contract MUST support multiple themes per frontend. -4. The contract MUST remain compiler-general and MUST NOT hardcode PBS as the universal model. -5. Hosts MUST remain adapters and MUST NOT become fallback authors of frontend visual identity. -6. Any derived plan MUST include an explicit migration path for PBS and explicit retirement of `semantic-highlighting.css` as canonical data. -7. Any derived plan MUST cover compiler contract changes, transport propagation, Studio consumption, and VS Code consumption. - -## Revision Log - -- 2026-05-06: Initial accepted decision from AGD-0036. -- 2026-05-06: Decomposed into PLN-0068, PLN-0069, PLN-0070, and PLN-0071. diff --git a/discussion/workflow/plans/PLN-0062-shell-session-and-state-cleanup-after-editor-removal.md b/discussion/workflow/plans/PLN-0062-shell-session-and-state-cleanup-after-editor-removal.md deleted file mode 100644 index 31268083..00000000 --- a/discussion/workflow/plans/PLN-0062-shell-session-and-state-cleanup-after-editor-removal.md +++ /dev/null @@ -1,91 +0,0 @@ ---- -id: PLN-0062 -ticket: studio-editor-workspace-cleanup -title: Shell Session and State Cleanup After Editor Removal -status: done -created: 2026-05-05 -completed: 2026-05-05 -tags: [studio, editor, cleanup, shell, session, state] ---- - -## Objective - -Remove the `Code Editor` workspace from the Studio shell and reconfigure project session and persisted state so the application remains coherent without any editor-owned concepts. - -## Background - -`DEC-0031` locks the complete removal of the embedded editor stack. The shell, project session, workspace registry, and `.studio/state.json` currently still assume the existence of `WorkspaceId.EDITOR`, `EditorWorkspace`, editor restoration state, and editor-specific layout state. - -## Scope - -### Included -- Remove `WorkspaceId.EDITOR` from the Studio shell. -- Remove `EditorWorkspace` registration and shell integration. -- Remove editor-specific state persistence and restoration paths. -- Remove `LSP`/`VFS` legacy ownership from `StudioProjectSession` and `StudioProjectSessionFactory`. -- Keep `Assets`, `Shipper`, `Debug`, launcher, and shell flows functional. - -### Excluded -- Removal of the `prometeu-lsp` and `prometeu-vfs` module source trees themselves. -- Documentation and lesson cleanup. -- New code backend or replacement LSP architecture. - -## Execution Steps - -### Step 1 - Remove editor workspace registration from the shell - -**What:** Remove all shell-level references to the `Code Editor` workspace. -**How:** Update the main window composition to stop creating `EditorWorkspace`, remove the editor rail item, stop selecting or restoring `WorkspaceId.EDITOR`, and ensure shell fallback remains stable when old persisted state still references the editor. -**File(s):** `prometeu-studio/src/main/java/p/studio/window/MainView.java`, `prometeu-studio/src/main/java/p/studio/workspaces/WorkspaceId.java`, any directly related shell controls or selectors. - -### Step 2 - Remove editor-owned state and restoration from project-local state - -**What:** Remove editor layout and restoration data from persisted project-local Studio state. -**How:** Simplify `ProjectLocalStudioState` to remove `editorRestoration` and `shellLayout.editorLayout`, update normalization/defaults, and make loading old `.studio/state.json` degrade safely without crashes or stale editor assumptions. -**File(s):** `prometeu-studio/src/main/java/p/studio/projectstate/ProjectLocalStudioState.java`, `prometeu-studio/src/main/java/p/studio/projectstate/ProjectLocalStudioStateService.java`, any callers that write or restore editor state. - -### Step 3 - Reconfigure project session to stop owning editor legacy dependencies - -**What:** Remove legacy editor-driven `LSP` and `VFS` ownership from project session composition. -**How:** Refactor `StudioProjectSession` and `StudioProjectSessionFactory` so opening a project no longer constructs `VfsProjectDocument` or `LspService`, and so close semantics remain valid without those resources. -**File(s):** `prometeu-studio/src/main/java/p/studio/projectsessions/StudioProjectSession.java`, `prometeu-studio/src/main/java/p/studio/projectsessions/StudioProjectSessionFactory.java`, dependent tests. - -### Step 4 - Remove bootstrap/container dependencies that only existed for the editor stack - -**What:** Remove application bootstrap and container seams that exist only to inject legacy editor stack services. -**How:** Delete `LspServiceFactory` and `ProjectDocumentVfsFactory` accessors from the container surfaces once shell/session no longer depend on them, and update `AppContainer` accordingly. -**File(s):** `prometeu-studio/src/main/java/p/studio/Container.java`, `prometeu-app/src/main/java/p/studio/AppContainer.java`, directly affected tests. - -## Test Requirements - -### Unit Tests -- Update session and state tests to reflect the absence of editor state. -- Add coverage for loading old persisted project-local state without editor restoration fields being required. - -### Integration Tests -- Verify the main Studio shell opens a project and activates a surviving workspace without editor registration. -- Verify session close still saves valid project-local state and shuts down surviving services cleanly. - -### Manual Verification -- Open the Studio shell and confirm only surviving workspaces appear. -- Reopen a project with stale `.studio/state.json` containing editor data and confirm safe fallback. -- Confirm project switching and shell startup remain stable. - -## Acceptance Criteria - -- [x] `WorkspaceId.EDITOR` no longer exists in production code. -- [x] `MainView` no longer instantiates or restores `EditorWorkspace`. -- [x] Project-local state no longer persists editor restoration or editor layout fields. -- [x] `StudioProjectSession` no longer owns legacy editor `LSP`/`VFS` resources. -- [x] The Studio shell remains functional with surviving workspaces. - -## Dependencies - -- `DEC-0031` accepted and normatively locked. -- Knowledge of all shell/session/state call sites that currently assume the editor exists. - -## Risks - -- Shell restoration may break if old persisted state is not normalized defensively. -- Session teardown may regress if hidden resource ownership remains after field removal. -- Removing editor assumptions too early may temporarily orphan callers still using editor-specific state APIs. diff --git a/discussion/workflow/plans/PLN-0063-legacy-lsp-and-vfs-module-removal-with-runtime-preservation.md b/discussion/workflow/plans/PLN-0063-legacy-lsp-and-vfs-module-removal-with-runtime-preservation.md deleted file mode 100644 index 62122162..00000000 --- a/discussion/workflow/plans/PLN-0063-legacy-lsp-and-vfs-module-removal-with-runtime-preservation.md +++ /dev/null @@ -1,91 +0,0 @@ ---- -id: PLN-0063 -ticket: studio-editor-workspace-cleanup -title: Legacy LSP and VFS Module Removal with Runtime Preservation -status: done -created: 2026-05-05 -completed: 2026-05-05 -tags: [studio, editor, cleanup, lsp, vfs, runtime] ---- - -## Objective - -Remove the legacy `prometeu-lsp` and `prometeu-vfs` modules and all remaining code references to them while preserving compiler, shipper, play, run, and debug flows that do not depend on the editor stack. - -## Background - -`DEC-0031` treats the current `prometeu-lsp` and `prometeu-vfs` modules as part of the embedded editor legacy stack. The Studio execution path must continue to compile, build, package, and run projects through the existing compiler and runtime orchestration layers. - -## Scope - -### Included -- Remove `prometeu-lsp` modules from Gradle settings and codebase references. -- Remove `prometeu-vfs` modules from Gradle settings and codebase references. -- Remove tests dedicated to these legacy modules. -- Verify `StudioShipperService`, `StudioPlayStopCoordinator`, and runtime/debug flows remain intact. - -### Excluded -- Shell/editor state cleanup handled by a separate plan. -- Documentation/spec/lesson cleanup handled by a separate plan. -- New replacement backend services. - -## Execution Steps - -### Step 1 - Remove Gradle module registration for legacy editor stack modules - -**What:** Stop building the legacy `prometeu-lsp` and `prometeu-vfs` modules. -**How:** Remove the module includes and any direct module dependencies that point to `prometeu-lsp:*` and `prometeu-vfs:*`, then fix resulting build graph fallout in Studio modules. -**File(s):** `settings.gradle.kts`, affected `build.gradle.kts` files in `prometeu-app`, `prometeu-studio`, and module directories. - -### Step 2 - Remove legacy module source trees and direct test coverage - -**What:** Delete the legacy `prometeu-lsp` and `prometeu-vfs` code once all consumers are detached. -**How:** Remove module source files and their dedicated tests only after production call sites no longer compile against them. -**File(s):** `prometeu-lsp/**`, `prometeu-vfs/**`, related test sources in `prometeu-studio`. - -### Step 3 - Preserve compiler and shipper build flow - -**What:** Ensure build preparation still uses the canonical compiler pipeline without editor legacy dependencies. -**How:** Validate and adjust `StudioShipperService` and any shipper/build callers so they continue using `BuilderPipelineService`, `BuilderPipelineConfig`, and `BuilderPipelineContext` directly without reintroducing removed editor-layer seams. -**File(s):** `prometeu-studio/src/main/java/p/studio/shipper/StudioShipperService.java`, affected compiler/shipper integration tests. - -### Step 4 - Preserve play, run, and debug execution flow - -**What:** Ensure runtime orchestration continues to function after legacy module removal. -**How:** Re-test and patch `StudioPlayStopCoordinator`, runtime handshake services, execution session handling, and debug workspace projections if any hidden import or event dependency pointed at removed editor-stack modules. -**File(s):** `prometeu-studio/src/main/java/p/studio/execution/StudioPlayStopCoordinator.java`, `prometeu-studio/src/main/java/p/studio/debug/runtime/**`, `prometeu-studio/src/main/java/p/studio/workspaces/debug/**`, related tests. - -## Test Requirements - -### Unit Tests -- Update or remove module-specific tests for `prometeu-lsp` and `prometeu-vfs`. -- Preserve unit coverage for execution session, play/stop coordination, and runtime handshake behavior. - -### Integration Tests -- Run compiler pipeline integration tests that cover `analyze`, `compile`, and `build`. -- Run shipper/build integration tests that exercise `StudioShipperService`. -- Run runtime/debug integration or coordinator tests that validate play/stop behavior. - -### Manual Verification -- Trigger Studio build flow and confirm artifact generation still works. -- Trigger Studio play flow and confirm runtime launch/stop still works. -- Open Debug and Shipper workspaces and confirm they remain operational. - -## Acceptance Criteria - -- [x] `prometeu-lsp` is no longer part of the build graph. -- [x] `prometeu-vfs` is no longer part of the build graph. -- [x] No production Studio class imports legacy `LSP` or `VFS` module types. -- [x] Compiler and shipper build flows still work. -- [x] Play/run/debug flows still work without the removed modules. - -## Dependencies - -- `DEC-0031` accepted and normatively locked. -- Shell/session cleanup completed enough that no surviving production code still requires legacy `LSP`/`VFS` types. - -## Risks - -- Hidden transitive dependencies may keep the build graph coupled to removed modules longer than expected. -- Runtime or debug flows may have indirect event or session assumptions not obvious from imports alone. -- Deleting modules too early may obscure compile errors that should instead be fixed in surviving Studio code first. diff --git a/discussion/workflow/plans/PLN-0064-normative-test-and-lesson-cleanup-for-editor-stack-removal.md b/discussion/workflow/plans/PLN-0064-normative-test-and-lesson-cleanup-for-editor-stack-removal.md deleted file mode 100644 index bf0bdd81..00000000 --- a/discussion/workflow/plans/PLN-0064-normative-test-and-lesson-cleanup-for-editor-stack-removal.md +++ /dev/null @@ -1,90 +0,0 @@ ---- -id: PLN-0064 -ticket: studio-editor-workspace-cleanup -title: Normative Test and Lesson Cleanup for Editor Stack Removal -status: done -created: 2026-05-05 -completed: 2026-05-05 -tags: [studio, editor, cleanup, docs, tests, lessons] ---- - -## Objective - -Remove or revise the normative documentation, tests, lessons, and user-facing resources that describe the embedded editor stack as a current Studio surface. - -## Background - -`DEC-0031` treats the editor stack removal as both code cleanup and normative cleanup. The repository currently contains active specs, README entries, i18n resources, and lessons that define `Code Editor`, `prometeu-vfs`, and the integrated semantic-read phase as active architecture. - -## Scope - -### Included -- Remove or rewrite Studio specs dedicated to the embedded editor stack. -- Update the Studio specs index and README. -- Remove or archive editor/LSP/VFS-specific tests that are no longer valid. -- Reclassify legacy lessons and references so they are not presented as active guidance. -- Remove user-facing i18n strings that only existed for the editor stack. - -### Excluded -- Implementation of shell/session/module cleanup itself. -- Future specs for the replacement backend or replacement external-editor strategy. - -## Execution Steps - -### Step 1 - Clean normative Studio specs - -**What:** Remove or replace specs that define the embedded editor stack as active architecture. -**How:** Delete or explicitly retire the `Code Editor`, `Project Document VFS`, and `Integrated LSP Semantic Read Phase` specs, then rewrite any remaining Studio README/index material so it no longer points to dead architecture. -**File(s):** `docs/specs/studio/5. Code Editor Workspace Specification.md`, `docs/specs/studio/6. Project Document VFS Specification.md`, `docs/specs/studio/7. Integrated LSP Semantic Read Phase Specification.md`, `docs/specs/studio/README.md`. - -### Step 2 - Clean user-facing resources and shell references - -**What:** Remove editor-specific strings, labels, and messages that no longer correspond to product surfaces. -**How:** Delete `workspace.code` and `codeEditor.*` message keys and any equivalent theme or resource references still tied to removed editor UI. -**File(s):** `prometeu-studio/src/main/resources/i18n/messages.properties`, any directly related theme or resource files. - -### Step 3 - Clean tests and update surviving expectations - -**What:** Remove tests whose sole purpose was validating the editor stack and update remaining tests to stop expecting that stack. -**How:** Delete or rewrite tests for editor workspace behavior, legacy `LSP`, legacy `VFS`, session expectations, and any shell assertions that still require the editor workspace. -**File(s):** `prometeu-studio/src/test/java/p/studio/projectsessions/**`, editor-related tests, `prometeu-lsp/**/test/**`, `prometeu-vfs/**/test/**`, any shell-level tests affected by workspace removal. - -### Step 4 - Reclassify lessons and historical references - -**What:** Ensure discussion lessons remain historically useful without being mistaken for current architecture. -**How:** Review the lessons and references tied to editor/VFS/LSP waves and either archive them, mark them as legacy, or update index/readme material so they are not treated as active operational guidance. -**File(s):** affected files under `discussion/lessons/DSC-0010*`, `DSC-0012*`, `DSC-0013*`, `DSC-0014*`, `DSC-0016*`, `DSC-0017*`, `DSC-0020*`, `DSC-0021*`, plus any summary/index surfaces that present them. - -## Test Requirements - -### Unit Tests -- Ensure no surviving test suite still references removed editor stack types or message keys. -- Add assertions where needed that remaining shell/resource state is internally consistent. - -### Integration Tests -- Validate the Studio docs/spec tree remains internally linked after removal or retirement of the editor specs. -- Validate the build/test graph no longer includes editor-stack-only suites. - -### Manual Verification -- Read the Studio spec README and confirm it no longer advertises the removed stack as active. -- Inspect project lessons/readme surfaces and confirm editor-stack lessons are clearly historical or retired. -- Launch the application and confirm no missing i18n keys or dead UI labels remain. - -## Acceptance Criteria - -- [x] Studio specs no longer define the embedded editor stack as an active surface. -- [x] Studio README/index material no longer points to removed editor/VFS/LSP architecture as current. -- [x] Editor-specific i18n keys are removed or no longer consumed. -- [x] Obsolete tests are removed or rewritten. -- [x] Historical lessons are clearly demoted from active operational guidance. - -## Dependencies - -- `DEC-0031` accepted and normatively locked. -- Sufficient implementation progress that the codebase no longer depends on the removed specs/resources/tests. - -## Risks - -- Removing normative docs too early may temporarily leave the repo without clear current guidance. -- Historical lessons may still be valuable; deleting them outright could lose context that should instead be reclassified. -- Partial cleanup can leave broken links or missing i18n keys that only appear at runtime. diff --git a/discussion/workflow/plans/PLN-0068-frontend-visual-contract-and-pbs-migration.md b/discussion/workflow/plans/PLN-0068-frontend-visual-contract-and-pbs-migration.md deleted file mode 100644 index 2a445745..00000000 --- a/discussion/workflow/plans/PLN-0068-frontend-visual-contract-and-pbs-migration.md +++ /dev/null @@ -1,118 +0,0 @@ ---- -id: PLN-0068 -ticket: frontend-visual-theme-spec-and-css-retirement -title: Frontend Visual Contract and PBS Migration -status: open -created: 2026-05-06 -completed: -tags: [compiler, compiler-general, frontend, pbs, presentation, theming, contract] ---- - -## Objective - -Introduce the canonical structured frontend visual contract in `FrontendSpec`, migrate PBS to that contract, and demote `semantic-highlighting.css` from authored truth to migration-only input. - -## Background - -`DEC-0033` locks that frontend visual intent must become structured canonical data, support multiple themes per frontend, remain token-centric, and retire authored host-consumed semantic CSS as the canonical source. - -PBS is the first frontend and therefore defines the first concrete migration path, but the contract MUST remain compiler-general rather than PBS-shaped by accident. - -## Scope - -### Included -- Evolve compiler/frontend metadata to publish a structured visual contract. -- Define the contract shape for semantic-token styling, editor surfaces, and theme identity. -- Migrate PBS to the new contract. -- Preserve any temporary migration utility needed to derive the first contract from the existing PBS CSS. -- Add validation tests that make the new contract normative and stable. - -### Excluded -- LSP transport changes. -- Studio rendering changes. -- VS Code runtime translation changes. - -## Non-Goals - -- Designing a generic host-owned theme engine. -- Supporting every possible frontend visual attribute in wave 1. -- Keeping authored CSS as a parallel canonical source. - -## Execution Steps - -### Step 1 - Define the structured visual contract in compiler-general surfaces - -**What:** Replace the resource-centric semantic presentation shape with a canonical structured visual contract in `FrontendSpec`. -**How:** Add or evolve frontend metadata models so each frontend can publish: - -1. semantic token vocabulary ownership, -2. one or more named visual themes, -3. token-centric visual rules, -4. editor-surface colors needed to preserve frontend identity. - -The model MUST be compiler-general and MUST NOT encode PBS-specific assumptions into the shared type system. -**File(s):** `prometeu-compiler/prometeu-compiler-core/src/main/java/p/studio/compiler/models/**`, affected frontend registry/definition surfaces. - -### Step 2 - Define the theme and token rule semantics explicitly - -**What:** Make the contract operational rather than descriptive. -**How:** Specify exact fields, invariants, and null/empty behavior for: - -1. theme identity, -2. theme selection metadata if needed at the contract layer, -3. token style rules, -4. editor surface colors, -5. versioning semantics inside or alongside `FrontendSpec`. - -The implementation MUST make it possible for hosts to translate the contract mechanically without inferring missing meaning. -**File(s):** `prometeu-compiler/prometeu-compiler-core/src/main/java/**`, associated tests in compiler modules. - -### Step 3 - Migrate PBS from authored CSS truth to structured contract truth - -**What:** Make PBS the first frontend to author the new contract. -**How:** Update `PBSDefinitions` and related PBS presentation metadata to publish one or more frontend-owned themes through the new contract. The existing `semantic-highlighting.css` MAY be parsed or manually transcribed to bootstrap the migration, but once the structured contract is in place, CSS MUST no longer be treated as authored truth. -**File(s):** `prometeu-compiler/frontends/prometeu-frontend-pbs/src/main/java/**`, `prometeu-compiler/frontends/prometeu-frontend-pbs/src/main/resources/themes/pbs/**`, related PBS tests. - -### Step 4 - Lock contract validity with tests - -**What:** Prevent future drift back to opaque resource ownership. -**How:** Add tests that assert: - -1. frontends publish structured visual themes, -2. PBS token vocabulary and theme definitions are coherent, -3. required token styles and editor-surface data resolve correctly, -4. authored CSS is no longer the canonical contract source. - -**File(s):** compiler-general and PBS test suites. - -## Test Requirements - -### Unit Tests -- Validate model invariants for theme IDs, token rules, and editor-surface fields. -- Validate `FrontendSpec` copies and exposes structured theme data safely. -- Validate PBS publishes at least one coherent theme using the new contract. - -### Integration Tests -- Run targeted compiler and PBS tests proving the contract compiles, resolves, and remains discoverable through frontend definitions. - -### Manual Verification -- Inspect the PBS frontend definition and confirm the structured contract is the readable authored source of truth. -- Confirm any remaining CSS is clearly migration-only or generated-output-only. - -## Acceptance Criteria - -- [ ] `FrontendSpec` publishes a structured canonical visual contract. -- [ ] The contract supports multiple themes per frontend. -- [ ] The contract is token-centric and can also express editor-surface colors. -- [ ] PBS is migrated to the new contract. -- [ ] `semantic-highlighting.css` is no longer treated as authored canonical frontend presentation data. - -## Dependencies - -- `DEC-0033` accepted and normatively locked. - -## Risks - -- Overfitting the first contract to PBS would weaken future frontend adoption. -- An underspecified token-style model would force host inference and violate the decision. -- Keeping CSS alive as a silent parallel truth source would nullify the migration. diff --git a/discussion/workflow/plans/PLN-0069-lsp-visual-theme-transport-and-selection.md b/discussion/workflow/plans/PLN-0069-lsp-visual-theme-transport-and-selection.md deleted file mode 100644 index abd4f549..00000000 --- a/discussion/workflow/plans/PLN-0069-lsp-visual-theme-transport-and-selection.md +++ /dev/null @@ -1,114 +0,0 @@ ---- -id: PLN-0069 -ticket: frontend-visual-theme-spec-and-css-retirement -title: LSP Visual Theme Transport and Theme Selection Propagation -status: open -created: 2026-05-06 -completed: -tags: [studio, lsp, protocol, transport, presentation, theming, compiler] ---- - -## Objective - -Extend the LSP boundary and transport surfaces so hosts receive frontend-owned visual theme data, theme identity, and active-theme information without collapsing that contract into host-authored categories. - -## Background - -`DEC-0033` requires LSP to transport enough structured frontend-owned visual information for hosts to render the active frontend theme, preserve frontend and token identity, and avoid forcing the extension to keep hand-maintained theme rules. - -The compiler contract itself is handled by `PLN-0068`. This plan covers the transport boundary that carries that contract into host adapters. - -## Scope - -### Included -- Extend internal LSP-facing description or capability surfaces to expose structured frontend visual contract data. -- Transport theme identity and active-theme information where needed. -- Preserve semantic token identity and frontend ownership through mapping layers. -- Add transport-level tests for the new visual contract payloads. - -### Excluded -- Defining the compiler-general contract itself. -- Studio-side rendering implementation. -- VS Code-side rendering implementation. - -## Non-Goals - -- Inventing host-owned fallback theme categories. -- Expanding LSP beyond what is required to carry the visual contract. -- Building transport that requires hand-curated per-frontend extension updates. - -## Execution Steps - -### Step 1 - Extend internal LSP descriptions to carry visual contract data - -**What:** Evolve the LSP-side server/bridge description surfaces to expose frontend-owned visual contract data instead of ad hoc token metadata only. -**How:** Update `lsp-api` and `lsp-v1` internal description models so they can carry: - -1. frontend identity, -2. semantic token legend identity, -3. available theme definitions or references, -4. active theme selection. - -The payload shape MUST remain faithful to the frontend contract and MUST NOT normalize it into host-owned abstractions. -**File(s):** `prometeu-lsp/prometeu-lsp-api/src/main/java/**`, `prometeu-lsp/prometeu-lsp-v1/src/main/java/**`. - -### Step 2 - Thread the visual contract through bridge and mapper layers - -**What:** Ensure the compiler-backed bridge and protocol mappers preserve visual theme data end to end. -**How:** Update bridge services, protocol mappers, server description responses, and any capability/bootstrap path that currently exposes token data so they now expose the structured visual contract and active theme metadata. -**File(s):** `prometeu-lsp/prometeu-lsp-v1/src/main/java/p/studio/lsp/services/**`, `.../messages/**`, `.../mapping/**`. - -### Step 3 - Define theme selection behavior for host consumption - -**What:** Make active-theme semantics operational. -**How:** Define and implement the transport rule for which theme a host should apply: - -1. single-theme frontend behavior, -2. multi-theme frontend behavior, -3. default theme behavior when no host override is in play, -4. how active-theme selection is surfaced to adapters. - -The transport MUST make host behavior deterministic without host-owned guessing. -**File(s):** `prometeu-lsp/prometeu-lsp-api/**`, `prometeu-lsp/prometeu-lsp-v1/**`, tests. - -### Step 4 - Add transport conformance tests - -**What:** Prevent regression back to token-only or host-shaped payloads. -**How:** Add tests that verify: - -1. theme payloads are present, -2. token identities survive transport unchanged, -3. active-theme information is deterministic, -4. no mapper collapses frontend-owned visual data into host-authored categories. - -**File(s):** `prometeu-lsp/prometeu-lsp-v1/src/test/java/**`, `prometeu-lsp/prometeu-lsp-api/src/test/java/**` if needed. - -## Test Requirements - -### Unit Tests -- Validate DTO/model invariants for theme payloads and active-theme fields. -- Validate mapper behavior for full visual contract transport. - -### Integration Tests -- Run targeted LSP tests proving a compiler-backed frontend description reaches the host adapter layer with visual theme data intact. - -### Manual Verification -- Inspect initialize/description pathways and confirm theme metadata is present and frontend-shaped. - -## Acceptance Criteria - -- [ ] LSP description/transport surfaces carry structured frontend visual theme data. -- [ ] Theme identity and active-theme semantics are deterministic. -- [ ] Semantic token identity remains frontend-owned end to end. -- [ ] No LSP layer introduces host-owned theme abstractions as canonical transport data. - -## Dependencies - -- `DEC-0033` accepted and normatively locked. -- `PLN-0068` for the compiler-side contract shape and PBS migration. - -## Risks - -- Transporting too little theme data would force host inference and violate the decision. -- Transporting host-shaped payloads would silently recreate the wrong ownership boundary. -- Theme selection semantics can become ambiguous unless explicitly defined in this plan. diff --git a/discussion/workflow/plans/PLN-0070-studio-visual-theme-adapter-and-css-retirement.md b/discussion/workflow/plans/PLN-0070-studio-visual-theme-adapter-and-css-retirement.md deleted file mode 100644 index 34ff0106..00000000 --- a/discussion/workflow/plans/PLN-0070-studio-visual-theme-adapter-and-css-retirement.md +++ /dev/null @@ -1,101 +0,0 @@ ---- -id: PLN-0070 -ticket: frontend-visual-theme-spec-and-css-retirement -title: Studio Visual Theme Adapter and CSS Retirement -status: open -created: 2026-05-06 -completed: -tags: [studio, editor, presentation, theming, adapter, css-retirement] ---- - -## Objective - -Make Studio consume the structured frontend visual contract as an adapter, remove any remaining dependency on authored frontend semantic CSS as the canonical source, and keep any host rendering mechanism clearly derivative. - -## Background - -`DEC-0033` locks that Studio is a rendering adapter over frontend-owned visual themes and that generated CSS is acceptable only as an adapter mechanism, not as the canonical frontend artifact. - -This plan applies that rule to the Studio side of the stack. - -## Scope - -### Included -- Update Studio-side presentation registries or rendering services to consume structured frontend visual contract data. -- Generate or map host rendering artifacts from the structured contract if Studio still needs CSS or equivalent host render descriptors. -- Remove reliance on authored frontend semantic CSS as a direct semantic presentation contract. -- Add Studio tests proving the adapter path is derivative and deterministic. - -### Excluded -- Compiler-side contract design. -- LSP transport contract design. -- VS Code adapter behavior. - -## Non-Goals - -- Rebuilding the deleted legacy Studio editor stack. -- Introducing Studio-owned frontend themes. -- Preserving authored semantic CSS as a parallel truth source. - -## Execution Steps - -### Step 1 - Update Studio presentation consumption to use the structured contract - -**What:** Make Studio consume frontend-owned visual theme data instead of resource-only semantic presentation. -**How:** Update presentation registries, semantic highlighting services, or other editor-related rendering seams so they resolve structured visual theme data from the frontend description path. -**File(s):** `prometeu-studio/src/main/java/**`, any remaining editor/presentation adapter surfaces still active after cleanup. - -### Step 2 - Derive host rendering artifacts from the contract - -**What:** Keep Studio rendering mechanical. -**How:** If Studio still requires CSS or CSS-like structures, generate or map them from the structured frontend visual contract. The host-generated artifact MUST be clearly derivative and MUST NOT be treated as authored frontend truth. -**File(s):** `prometeu-studio/src/main/java/**`, possible theme/presentation helper modules, generated resource paths if adopted. - -### Step 3 - Remove direct canonical dependence on frontend semantic CSS - -**What:** Retire the old consumption model. -**How:** Remove or rewrite any code path that treats frontend semantic CSS resources as the canonical semantic presentation input. Leave only temporary compatibility or generated-output behavior if strictly needed during rollout. -**File(s):** `prometeu-studio/**`, related frontend resource loading code. - -### Step 4 - Add Studio adapter conformance tests - -**What:** Lock the adapter boundary. -**How:** Add tests that verify: - -1. Studio consumes structured frontend visual themes, -2. token style rendering inputs are contract-derived, -3. any generated CSS is derivative, -4. Studio does not silently fall back to host-authored frontend theme logic. - -**File(s):** `prometeu-studio/src/test/java/**` and any relevant integration test modules. - -## Test Requirements - -### Unit Tests -- Validate contract-to-rendering translation logic. -- Validate theme selection consumption on the Studio side. - -### Integration Tests -- Run targeted Studio-side tests proving frontend presentation resolves from structured contract data and not from authored semantic CSS. - -### Manual Verification -- Inspect the Studio path and confirm remaining CSS, if any, is generated or compatibility-only. - -## Acceptance Criteria - -- [ ] Studio consumes structured frontend visual contract data. -- [ ] Any Studio-side CSS or equivalent rendering descriptor is derivative, not canonical. -- [ ] Direct canonical dependence on authored frontend semantic CSS is removed. -- [ ] Studio does not reauthor frontend visual identity locally. - -## Dependencies - -- `DEC-0033` accepted and normatively locked. -- `PLN-0068` for the canonical compiler/frontend contract. -- `PLN-0069` for transport of visual contract data into the host boundary. - -## Risks - -- Studio may still hide old CSS assumptions in helper layers unless the migration is exhaustive. -- Generated CSS can accidentally become the new silent truth source if ownership boundaries are not explicit in code and tests. -- Residual editor cleanup from earlier refactors may obscure the remaining active consumption path. diff --git a/discussion/workflow/plans/PLN-0071-vscode-dynamic-theme-translation-adapter.md b/discussion/workflow/plans/PLN-0071-vscode-dynamic-theme-translation-adapter.md deleted file mode 100644 index a7cdbf4c..00000000 --- a/discussion/workflow/plans/PLN-0071-vscode-dynamic-theme-translation-adapter.md +++ /dev/null @@ -1,100 +0,0 @@ ---- -id: PLN-0071 -ticket: frontend-visual-theme-spec-and-css-retirement -title: VS Code Dynamic Theme Translation Adapter -status: open -created: 2026-05-06 -completed: -tags: [vscode, extension, lsp, presentation, theming, adapter] ---- - -## Objective - -Turn the VS Code extension into a stable adapter that translates frontend-owned visual theme contracts into VS Code-compatible rendering behavior without requiring source edits for routine frontend theme changes. - -## Background - -`DEC-0033` explicitly locks that the extension must not become a repository of manually curated frontend theme rules. The extension must translate the contract it receives rather than being edited whenever a frontend changes colors, emphasis, or theme variants. - -This plan covers the client-side adapter behavior that satisfies that requirement. - -## Scope - -### Included -- Replace hardcoded per-frontend visual theme rules with dynamic or generated translation based on the transported frontend contract. -- Define the minimum static VS Code contribution surface still required by the platform. -- Support multi-theme frontend data consumption and active-theme application. -- Add extension tests or verification coverage around theme translation. - -### Excluded -- Compiler-side contract definition. -- LSP transport definition. -- Studio rendering behavior. - -## Non-Goals - -- Building a general-purpose VS Code theme marketplace artifact. -- Allowing the extension to become a second authored source of frontend theme truth. -- Solving unrelated reconnect or transport lifecycle issues beyond what this adapter needs. - -## Execution Steps - -### Step 1 - Identify the minimal static VS Code contribution surface - -**What:** Separate what the extension must declare statically from what it can translate dynamically. -**How:** Keep only the minimal `package.json` contribution data required for VS Code to recognize semantic token kinds or activate the extension. Remove hardcoded frontend-specific color rules from static configuration where dynamic translation can take over. -**File(s):** `tools/vscode-extension/package.json`, related extension bootstrap files. - -### Step 2 - Implement contract-to-VS Code theme translation - -**What:** Translate frontend-owned visual contract data into VS Code-understandable configuration. -**How:** Update extension runtime code to receive the transported visual theme contract, map token and editor-surface data into the VS Code APIs/configuration model, and apply the active frontend theme deterministically. -**File(s):** `tools/vscode-extension/src/**`, mirrored build outputs only if local toolchain constraints require temporary manual sync. - -### Step 3 - Support multi-theme frontends without extension source edits - -**What:** Make frontend theme growth operationally cheap. -**How:** Ensure that adding or changing frontend-owned themes does not require new extension source logic unless the VS Code platform itself introduces a new capability boundary. Theme identity, token rules, and active selection must be data-driven. -**File(s):** `tools/vscode-extension/src/**`, possible supporting protocol model surfaces if consumed directly. - -### Step 4 - Add adapter verification coverage - -**What:** Protect the no-manual-theme-maintenance rule. -**How:** Add tests or deterministic verification around: - -1. translation of token rules, -2. translation of editor-surface colors where supported, -3. handling of multiple frontend themes, -4. absence of hardcoded PBS-only theme logic in the adapter path. - -**File(s):** `tools/vscode-extension/src/test/**` if present, or equivalent test harness/verification approach adopted by the extension module. - -## Test Requirements - -### Unit Tests -- Validate translation of structured token rules into VS Code-compatible theme rules. -- Validate active-theme switching behavior for data-driven frontend themes. - -### Integration Tests -- Run extension-targeted validation proving the frontend contract can change without source-level theme edits. - -### Manual Verification -- Open PBS content through the extension and confirm the active theme is applied from transported contract data rather than hardcoded `package.json` color tables. - -## Acceptance Criteria - -- [ ] The extension no longer depends on hardcoded frontend-specific theme rules as the primary rendering source. -- [ ] Frontend theme changes are driven by contract data rather than extension source edits. -- [ ] Multi-theme frontend payloads can be translated and applied deterministically. -- [ ] The remaining static VS Code contribution surface is minimal and structural only. - -## Dependencies - -- `DEC-0033` accepted and normatively locked. -- `PLN-0069` for transport of visual theme data to the extension. - -## Risks - -- VS Code platform constraints may force a hybrid static/runtime model that must stay carefully bounded. -- The current local Node/TypeScript environment issues can slow validation. -- Leaving too much theme data in `package.json` would preserve the current maintenance problem under a new name. -- 2.47.2 From 240525286b34348bf3b9b10d84b4d7900f0da892 Mon Sep 17 00:00:00 2001 From: bQUARKz Date: Fri, 8 May 2026 09:48:14 +0100 Subject: [PATCH 33/37] Wave 1 de assistencia editorial via LSP para PBS no VS Code --- discussion/index.ndjson | 4 +- ...D-0038-pbs-lsp-editor-assistance-wave-1.md | 207 ++++++++++++++++++ ...symbol-documentation-and-hover-markdown.md | 137 ++++++++++++ ...C-0035-pbs-lsp-editor-assistance-wave-1.md | 192 ++++++++++++++++ ...face-for-symbols-members-and-signatures.md | 135 ++++++++++++ ...ignature-help-over-editorial-resolution.md | 121 ++++++++++ ...and-wave-1-editor-assistance-validation.md | 103 +++++++++ 7 files changed, 898 insertions(+), 1 deletion(-) create mode 100644 discussion/workflow/agendas/AGD-0038-pbs-lsp-editor-assistance-wave-1.md create mode 100644 discussion/workflow/agendas/AGD-0039-pbs-symbol-documentation-and-hover-markdown.md create mode 100644 discussion/workflow/decisions/DEC-0035-pbs-lsp-editor-assistance-wave-1.md create mode 100644 discussion/workflow/plans/PLN-0075-pbs-editorial-resolution-surface-for-symbols-members-and-signatures.md create mode 100644 discussion/workflow/plans/PLN-0076-lsp-completion-hover-and-signature-help-over-editorial-resolution.md create mode 100644 discussion/workflow/plans/PLN-0077-vscode-consumption-and-wave-1-editor-assistance-validation.md diff --git a/discussion/index.ndjson b/discussion/index.ndjson index 67ad4756..f52fcf37 100644 --- a/discussion/index.ndjson +++ b/discussion/index.ndjson @@ -1,4 +1,6 @@ -{"type":"meta","next_id":{"DSC":35,"AGD":38,"DEC":35,"PLN":75,"LSN":51,"CLSN":1}} +{"type":"meta","next_id":{"DSC":37,"AGD":40,"DEC":36,"PLN":78,"LSN":51,"CLSN":1}} +{"type":"discussion","id":"DSC-0036","status":"open","ticket":"pbs-symbol-documentation-and-hover-markdown","title":"Modelo de documentacao de simbolos em PBS e consumo markdown no hover","created_at":"2026-05-08","updated_at":"2026-05-08","tags":["compiler","compiler-pbs","studio","lsp","vscode","editor","hover","documentation","markdown"],"agendas":[{"id":"AGD-0039","file":"AGD-0039-pbs-symbol-documentation-and-hover-markdown.md","status":"open","created_at":"2026-05-08","updated_at":"2026-05-08"}],"decisions":[],"plans":[],"lessons":[]} +{"type":"discussion","id":"DSC-0035","status":"in_progress","ticket":"pbs-lsp-editor-assistance-wave-1","title":"Wave 1 de assistencia editorial via LSP para PBS no VS Code","created_at":"2026-05-08","updated_at":"2026-05-08","tags":["studio","lsp","vscode","compiler","compiler-pbs","editor","completion","hover","signature-help"],"agendas":[{"id":"AGD-0038","file":"AGD-0038-pbs-lsp-editor-assistance-wave-1.md","status":"accepted","created_at":"2026-05-08","updated_at":"2026-05-08"}],"decisions":[{"id":"DEC-0035","file":"DEC-0035-pbs-lsp-editor-assistance-wave-1.md","status":"accepted","created_at":"2026-05-08","updated_at":"2026-05-08","ref_agenda":"AGD-0038"}],"plans":[{"id":"PLN-0075","file":"PLN-0075-pbs-editorial-resolution-surface-for-symbols-members-and-signatures.md","status":"open","created_at":"2026-05-08","updated_at":"2026-05-08","ref_decisions":["DEC-0035"]},{"id":"PLN-0076","file":"PLN-0076-lsp-completion-hover-and-signature-help-over-editorial-resolution.md","status":"open","created_at":"2026-05-08","updated_at":"2026-05-08","ref_decisions":["DEC-0035"]},{"id":"PLN-0077","file":"PLN-0077-vscode-consumption-and-wave-1-editor-assistance-validation.md","status":"open","created_at":"2026-05-08","updated_at":"2026-05-08","ref_decisions":["DEC-0035"]}],"lessons":[]} {"type":"discussion","id":"DSC-0034","status":"done","ticket":"frontend-semantic-host-projection-flexibility","title":"Frontend semantic vocabulary flexibility and declarative host projection","created_at":"2026-05-06","updated_at":"2026-05-07","tags":["compiler","compiler-general","frontend","semantics","vscode","host-projection","lsp"],"agendas":[],"decisions":[],"plans":[],"lessons":[{"id":"LSN-0048","file":"discussion/lessons/DSC-0034-frontend-semantic-host-projection-flexibility/LSN-0048-frontend-owned-semantic-vocabularies-with-declarative-host-projection.md","status":"done","created_at":"2026-05-07","updated_at":"2026-05-07"}]} {"type":"discussion","id":"DSC-0033","status":"done","ticket":"frontend-visual-theme-spec-and-css-retirement","title":"Frontend visual theme spec and retirement of host-consumed semantic CSS","created_at":"2026-05-06","updated_at":"2026-05-08","tags":["compiler","compiler-general","frontend","presentation","theming","studio","vscode","lsp","pbs"],"agendas":[],"decisions":[],"plans":[],"lessons":[{"id":"LSN-0050","file":"discussion/lessons/DSC-0033-frontend-visual-theme-spec-and-css-retirement/LSN-0050-frontend-owned-visual-themes-with-structured-contract-and-host-adapters.md","status":"done","created_at":"2026-05-08","updated_at":"2026-05-08"}]} {"type":"discussion","id":"DSC-0032","status":"done","ticket":"studio-new-lsp-api-and-v1-boundary","title":"Novo boundary entre lsp-api, lsp-v1 e a extensao VS Code","created_at":"2026-05-05","updated_at":"2026-05-07","tags":["studio","lsp","vscode","protocol","api","boundary"],"agendas":[],"decisions":[],"plans":[],"lessons":[{"id":"LSN-0047","file":"discussion/lessons/DSC-0032-studio-new-lsp-api-and-v1-boundary/LSN-0047-project-scoped-lsp-boundary-and-protocol-containment.md","status":"done","created_at":"2026-05-07","updated_at":"2026-05-07"}]} diff --git a/discussion/workflow/agendas/AGD-0038-pbs-lsp-editor-assistance-wave-1.md b/discussion/workflow/agendas/AGD-0038-pbs-lsp-editor-assistance-wave-1.md new file mode 100644 index 00000000..f31beaf2 --- /dev/null +++ b/discussion/workflow/agendas/AGD-0038-pbs-lsp-editor-assistance-wave-1.md @@ -0,0 +1,207 @@ +--- +id: AGD-0038 +ticket: pbs-lsp-editor-assistance-wave-1 +title: Wave 1 de assistencia editorial via LSP para PBS no VS Code +status: accepted +created: 2026-05-08 +resolved: 2026-05-08 +decision: DEC-0035 +tags: [studio, lsp, vscode, compiler, compiler-pbs, editor, completion, hover, signature-help] +--- + +## Pain + +O stack atual de PBS no VS Code ja entrega duas capacidades relevantes: + +- diagnostics basicos; +- semantic highlighting com tema frontend-owned. + +Mas ele ainda nao entrega o minimo de assistencia editorial para um fluxo real de escrita de codigo: + +- nao existe `completion`; +- `hover` ainda eh placeholder; +- nao existe `signature help`. + +Sem isso, o editor continua servindo mais como viewer colorido com erros do que como ambiente minimamente utilizavel para escrever PBS com conforto. + +## Context + +Domain owner: `studio` + +Subdomains touched: + +- `studio/lsp` +- `compiler/pbs` +- `compiler/general` + +Estado atual observado no codigo: + +- o servidor anuncia `hover` e `semanticTokens`, mas nao anuncia `completionProvider`, `signatureHelpProvider` ou `documentFormattingProvider`; +- o bridge interno do LSP so expõe `describeServer`, `analyzeDocument`, `hover`, `semanticTokens` e `onSave`; +- `hover` hoje retorna texto fixo, sem usar simbolo, assinatura, tipo ou docs; +- o pipeline do compiler ja consegue analisar overlay do documento e possui superficies semanticas e de linking relevantes no PBS; +- o highlighting recente ja resolve bastante informacao lexical e parte da superficie stdlib/imports. + +Esta agenda trata apenas da wave 1 de assistencia editorial. +Ela nao tenta fechar todo o problema de IDE features. + +## Open Questions + +- Qual deve ser o escopo minimo de `completion` para chamarmos essa wave de utilizavel? +- [x] Qual deve ser o escopo minimo de `completion` para chamarmos essa wave de utilizavel? + R: keywords, nomes locais em escopo, simbolos importados/publicos, e members apos `.` para superfícies reconhecidas (`service`, `host`, `builtin type`, `struct` e constructors/funcoes relacionados). Sem isso, a feature ainda nao ajuda na descoberta real da API. +- `completion` deve nascer apenas com heuristicas lexicais/sintaticas, ou ja deve usar semantica e linking do compiler onde isso for viavel? +- [x] `completion` deve nascer apenas com heuristicas lexicais/sintaticas, ou ja deve usar semantica e linking do compiler onde isso for viavel? + R: deve nascer compiler-backed sempre que a informacao ja existir de forma confiavel no pipeline semantico/linking. Heuristica local pode existir apenas como complemento estritamente limitado para casos ainda nao resolvidos, nunca como segunda semantica canônica. +- Em `hover`, quais informacoes sao obrigatorias na primeira entrega: + assinatura, kind, modulo de origem, tipo inferido, documentacao? +- [x] Em `hover`, quais informacoes sao obrigatorias na primeira entrega: + assinatura, kind, modulo de origem, tipo inferido, documentacao? + R: obrigatorios: `kind`, assinatura quando aplicavel, modulo/origem quando relevante, e tipo/shape basico quando houver. Documentacao textual eh desejavel para stdlib e builtins, mas nao deve bloquear a wave 1 se a infraestrutura de docstring ainda nao existir. Se a linguagem vier a adotar algo como `Document(...)` com markdown pronto para hover, isso deve nascer em discussao propria; nesta wave atual, basta preparar o local de consumo para documentacao opcional quando ela existir. +- `signature help` deve usar a mesma fonte semantica de `hover/completion`, ou pode nascer numa implementacao mais local para chamadas conhecidas? +- [x] `signature help` deve usar a mesma fonte semantica de `hover/completion`, ou pode nascer numa implementacao mais local para chamadas conhecidas? + R: deve usar a mesma base semantica. O objetivo da wave eh justamente evitar tres caminhos tecnicos diferentes para responder "qual assinatura esta sendo chamada?". +- Como tratar membros de stdlib, aliases importados, services, hosts, builtin types e metodos de struct sem criar uma segunda semantica paralela no LSP? +- [x] Como tratar membros de stdlib, aliases importados, services, hosts, builtin types e metodos de struct sem criar uma segunda semantica paralela no LSP? + R: o LSP deve perguntar ao compiler por uma superficie editorial/resolutiva unica, derivada das mesmas fontes usadas para analise, linking, stdlib e metadata do frontend. O LSP nao deve reconstruir manualmente tabelas paralelas de membros. +- Esta wave deve incluir `go to definition`, ou isso deve ficar explicitamente fora do escopo para nao diluir a entrega? +- [x] Esta wave deve incluir `go to definition`, ou isso deve ficar explicitamente fora do escopo para nao diluir a entrega? + R: deve ficar fora do escopo desta wave. Ele eh um proximo passo natural, mas nao eh requisito para chamar `completion + hover + signature help` de minimamente utilizaveis. +- Formatacao e identacao automatica devem ficar fora desta agenda como non-goal explicito? +- [x] Formatacao e identacao automatica devem ficar fora desta agenda como non-goal explicito? + R: sim. Podem virar discussao/plan posterior. Nesta wave, elas seriam custo adicional sem impacto proporcional comparado a completion/hover/signature help. + +## Options + +### Option A - Completion e hover por heuristica leve, com signature help posterior + +- **Approach:** implementar `completion` usando contexto local, imports, keywords e alguns casos de member access, implementar `hover` com informacao minima, e deixar `signature help` para uma wave seguinte. +- **Pro:** menor custo inicial e menor risco de travar na arquitetura semantica. +- **Con:** pode criar uma primeira entrega inconsistente, especialmente em chamadas de stdlib e tipos importados, e pode forcar refactor cedo demais depois. +- **Maintainability:** media. + +### Option B - Wave 1 coerente com completion, hover e signature help sobre uma mesma base semantica + +- **Approach:** desenhar uma pequena superficie de assistencia editorial no LSP que use uma base comum para resolver simbolos, membros e assinaturas. Entregar juntos: + - completion minimo utilizavel; + - hover real; + - signature help em chamadas. +- **Pro:** evita duplicacao conceitual e produz uma experiencia de editor mais consistente desde a primeira wave. +- **Con:** custo maior de desenho e implementacao agora. +- **Maintainability:** forte. + +### Option C - Adiar assistencia semantica e depender do VS Code + snippets + +- **Approach:** manter diagnostics e colors como estao, adicionar no maximo snippets ou pequenas ajudas na extensao. +- **Pro:** quase nenhum custo de backend. +- **Con:** nao resolve o problema real; o editor continua insuficiente para escrita cotidiana de PBS. +- **Maintainability:** fraca. + +## Tradeoffs + +Option C nao fecha a dor real e deve ser descartada. + +Option A parece atraente para ganhar velocidade, mas carrega um risco ruim: + +- introduzir `completion`, `hover` e depois `signature help` por caminhos tecnicos diferentes; +- duplicar logica entre parser local, heuristicas e linking; +- e transformar a wave 2 num retrabalho de consolidacao. + +Option B custa mais, mas o custo eh justificavel porque estas tres features se apoiam nas mesmas perguntas: + +- o que este simbolo representa? +- quais membros ele expõe? +- qual eh a assinatura desta chamada? +- qual o modulo/origem deste item? + +Se essas perguntas forem respondidas por uma base comum, a wave 1 fica mais coerente e abre caminho natural para futuras features como `definition`, `references` e `inlay hints` via LSP. + +## Recommendation + +Seguir com **Option B**. + +A recomendacao eh abrir uma wave 1 coerente de assistencia editorial com: + +- `completion` minimo utilizavel; +- `hover` funcional; +- `signature help` funcional. + +Escopo minimo recomendado para `completion`: + +- keywords; +- simbolos locais em escopo; +- nomes importados/publicos relevantes; +- members apos `.` para stdlib, builtin types, structs e services/hosts reconhecidos. + +Escopo minimo recomendado para `hover`: + +- kind do simbolo; +- assinatura quando aplicavel; +- modulo/origem quando relevante; +- tipo ou shape basico quando isso existir de forma confiavel. + +Escopo minimo recomendado para `signature help`: + +- chamadas de funcao/metodo/construtor; +- parametro ativo; +- labels consistentes com a mesma representacao de assinatura usada no hover. + +## Discussion + +O ponto principal desta agenda nao eh “adicionar IDE features” genericamente. + +O ponto principal eh definir a primeira wave de superfícies de assistencia que tiram o PBS no VS Code do estado de: + +- diagnostics + coloracao + +para um estado de: + +- escrita assistida minima, com descoberta de API e leitura de assinatura. + +Isso exige disciplina de boundary. + +O VS Code extension nao deve inventar semantica local. +O servidor LSP deve continuar sendo o owner da assistencia editorial. + +Da mesma forma, o LSP nao deve criar uma semantica paralela desconectada do compiler se ja existe informacao aproveitavel em parser, linking, stdlib e superficies semanticas do PBS. + +Tambem vale explicitar o que fica fora desta agenda: + +- formatter completo; +- identacao automatica robusta de documento; +- quick fixes; +- definition/references; +- rename; +- code actions mais amplas. + +Esses itens podem virar agenda posterior. + +Tambem fica registrado um criterio importante de arquitetura: + +- o primeiro passo nao eh encher o protocolo de features; +- o primeiro passo eh criar uma base editorial coerente no lado `compiler/pbs` + `studio/lsp` que consiga responder simbolo, members e assinatura; +- `completion`, `hover` e `signature help` sao projeções diferentes sobre a mesma base. + +E um criterio adicional de preparacao editorial: + +- a wave 1 deve prever um campo/superficie opcional de documentacao no modelo editorial resolvido por simbolo; +- mas a autoria dessa documentacao na linguagem PBS, inclusive eventual anotacao `Document(...)` com markdown, fica fora desta agenda e pode seguir para discussao separada. + +## Resolution + +Resolucao preliminar: + +- a wave 1 deve ser considerada valida quando o VS Code conseguir oferecer descoberta minima de API, leitura de assinatura e ajuda em chamadas sem depender de conhecimento local na extensao; +- `completion`, `hover` e `signature help` devem nascer sobre uma mesma base compiler-backed; +- `go to definition`, formatter e outras features de IDE ficam explicitamente fora do escopo. + +Se esta leitura fizer sentido, o proximo passo eh aceitar a agenda e fechar uma `decision` que: + +1. defina o escopo normativo exato de `completion`, `hover` e `signature help`; +2. fixe o boundary entre `compiler/pbs`, `studio/lsp` e `tools/vscode-extension`; +3. declare explicitamente os non-goals desta wave; +4. determine se a base deve nascer compiler-backed desde o inicio ou com alguma heuristica local estritamente limitada. + +## Next Step + +Se voce concordar com o enquadramento, eu converto esta agenda em `accepted` e escrevo a `decision` normativa da wave 1 de assistencia editorial para PBS no VS Code. diff --git a/discussion/workflow/agendas/AGD-0039-pbs-symbol-documentation-and-hover-markdown.md b/discussion/workflow/agendas/AGD-0039-pbs-symbol-documentation-and-hover-markdown.md new file mode 100644 index 00000000..c3c0504b --- /dev/null +++ b/discussion/workflow/agendas/AGD-0039-pbs-symbol-documentation-and-hover-markdown.md @@ -0,0 +1,137 @@ +--- +id: AGD-0039 +ticket: pbs-symbol-documentation-and-hover-markdown +title: Modelo de documentacao de simbolos em PBS e consumo markdown no hover +status: open +created: 2026-05-08 +tags: [compiler, compiler-pbs, studio, lsp, vscode, editor, hover, documentation, markdown] +--- + +## Pain + +A wave atual de assistencia editorial quer `hover` util, mas ainda nao existe um modelo claro para documentacao authored dentro de PBS. + +Sem esse modelo, o hover pode até mostrar: + +- kind; +- assinatura; +- origem; +- tipo/shape. + +Mas continua sem uma superficie limpa para explicar intencao de uso, contrato semantico, detalhes de parametros ou observacoes de API. + +Hoje a ideia proposta eh algo como: + +- `Document(qualquer markdown aqui dentro...)` + +como anotacao consumida diretamente pelo hover. + +Isso parece simples no uso, mas toca em decisoes de linguagem e contrato editorial que merecem discussao propria. + +## Context + +Domain owner: `compiler/pbs` + +Subdomains touched: + +- `compiler/general` +- `studio/lsp` +- `tools/vscode-extension` + +Esta agenda eh deliberadamente separada de `AGD-0038`. + +Razao: + +- `AGD-0038` trata da wave 1 de `completion`, `hover` e `signature help`; +- esta nova agenda trata da autoria, armazenamento, propagacao e consumo de documentacao de simbolos. + +O objetivo eh evitar que a primeira wave de assistencia editorial fique bloqueada por uma decisao de linguagem ainda nao fechada. + +## Open Questions + +- A autoria da documentacao deve acontecer por anotacao explicita como `Document(...)`, por comentario estruturado, ou por outro mecanismo? +- O payload authored deve aceitar markdown arbitrario como fonte canonica, ou deve haver alguma normalizacao/restricao? +- Quais simbolos podem carregar documentacao na wave inicial: + funcoes, methods, services, hosts, builtin types, structs, enums, fields, constructors? +- A documentacao deve viver no AST/semantics como superficie compiler-backed explicita? +- Como a documentacao authored em PBS se relaciona com documentacao de stdlib gerada ou importada de outras fontes? +- O hover deve consumir markdown pronto sem transformacao, ou deve haver um pipeline intermediario de sanitizacao/normalizacao? +- Como tratar multilinhas, escaping e ergonomia de escrita se a surface for `Document(...)`? +- A agenda deve definir apenas o modelo de autoria, ou tambem o transporte LSP e a composicao final do hover? + +## Options + +### Option A - Anotacao `Document(...)` com markdown como payload canonico + +- **Approach:** introduzir uma anotacao explicita na linguagem PBS cujo conteudo ja eh markdown pronto para o hover. +- **Pro:** autoria direta, intencao clara, pipeline simples de consumo no LSP e no hover. +- **Con:** precisa desenhar sintaxe, escaping, multiline e regras de onde a anotacao eh permitida. +- **Maintainability:** forte se a surface de linguagem ficar limpa. + +### Option B - Comentarios estruturados como fonte de documentacao + +- **Approach:** usar comentarios especiais ou doc-comments, com parser especifico para gerar documentacao de simbolo. +- **Pro:** mais familiar para quem vem de outras linguagens e menos intrusivo no corpo semantico da linguagem. +- **Con:** exige novo contrato de binding entre comentarios e simbolos, e pode aumentar ambiguidade editorial. +- **Maintainability:** media. + +### Option C - Nao definir autoria em PBS agora e suportar apenas docs de stdlib por metadata externa + +- **Approach:** deixar a linguagem sem surface authored por enquanto e alimentar hover apenas com docs externas/geradas. +- **Pro:** menor custo imediato de linguagem. +- **Con:** resolve mal a autoria de codigo de usuario e deixa o modelo incompleto. +- **Maintainability:** fraca. + +## Tradeoffs + +Option C nao parece suficiente como direcao de produto se a intencao eh ter hover realmente util para APIs authored em PBS. + +Option B eh plausivel, mas move o problema para um binding entre comentario e simbolo que tambem precisa ser projetado com cuidado. Isso costuma parecer mais barato do que realmente eh. + +Option A tem um custo claro de sintaxe e modelo, mas pelo menos deixa explicito que documentacao eh metadado semantico e nao apenas texto solto ao redor do codigo. + +Se a equipe realmente quer markdown authored pronto para consumo no hover, Option A parece a discussao mais direta e honesta. + +## Recommendation + +Discutir esta agenda com viés inicial para **Option A**, mas sem fechar ainda a sintaxe final. + +A recomendacao preliminar eh separar o problema em duas perguntas: + +1. qual eh a surface canonical de autoria da documentacao em PBS? +2. como essa documentacao vira um payload editorial resolvido para hover e futuros consumers? + +Mesmo que `Document(...)` seja a direcao vencedora, a decisao deve deixar claro: + +- onde ela pode ser usada; +- qual formato textual aceita; +- como ela eh preservada no compiler; +- como chega ao LSP; +- e como o hover deve compor isso com assinatura e metadados do simbolo. + +## Discussion + +Esta agenda nao deve ser reduzida a "mostrar markdown no hover". + +O problema real eh definir ownership e boundary da documentacao: + +- o author escreve onde? +- o compiler preserva como? +- o LSP transporta em qual shape? +- o hover monta o resultado com qual ordem e responsabilidade? + +Tambem vale observar que a escolha aqui pode influenciar mais do que hover: + +- completions futuras podem querer `detail` e `documentation`; +- signature help pode querer descricoes de parametros; +- docs de stdlib podem querer surface unificada com docs authored. + +Por isso, mesmo sendo uma agenda separada, ela conversa diretamente com a futura qualidade do editor. + +## Resolution + +Ainda em aberto. + +## Next Step + +Se o enquadramento fizer sentido, o proximo passo eh discutir as open questions e fechar uma `decision` propria para o modelo de documentacao de simbolos em PBS. diff --git a/discussion/workflow/decisions/DEC-0035-pbs-lsp-editor-assistance-wave-1.md b/discussion/workflow/decisions/DEC-0035-pbs-lsp-editor-assistance-wave-1.md new file mode 100644 index 00000000..9991f391 --- /dev/null +++ b/discussion/workflow/decisions/DEC-0035-pbs-lsp-editor-assistance-wave-1.md @@ -0,0 +1,192 @@ +--- +id: DEC-0035 +ticket: pbs-lsp-editor-assistance-wave-1 +title: Wave 1 de assistencia editorial via LSP para PBS no VS Code +status: accepted +created: 2026-05-08 +accepted: 2026-05-08 +agenda: AGD-0038 +plans: [PLN-0075, PLN-0076, PLN-0077] +tags: [studio, lsp, vscode, compiler, compiler-pbs, editor, completion, hover, signature-help] +--- + +## Context + +O stack atual de PBS no VS Code ja entrega diagnostics basicos e semantic highlighting frontend-owned, mas ainda nao oferece assistencia editorial minima para escrita cotidiana de codigo. + +Hoje: + +1. nao existe `completion`; +2. `hover` existe apenas como placeholder; +3. nao existe `signature help`; +4. o servidor ainda nao anuncia capabilities correspondentes para essas superficies; +5. o compiler e o frontend PBS ja possuem informacao semantica, de linking, stdlib e metadata suficiente para nao precisarmos inventar uma segunda semantica local na extensao. + +Esta decisao trata apenas da primeira wave de assistencia editorial para PBS no VS Code. +Ela nao cobre formatter, identacao automatica robusta, quick fixes, `go to definition`, `references`, `rename` nem code actions gerais. + +## Decision + +O repositório SHALL entregar uma wave 1 de assistencia editorial via LSP para PBS no VS Code com tres superfícies funcionais: + +1. `completion`; +2. `hover`; +3. `signature help`. + +Esta wave SHALL ser considerada valida quando essas tres superfícies permitirem: + +1. descoberta minima de API; +2. leitura de assinatura em simbolos e chamadas; +3. ajuda de chamada sem dependencia de conhecimento semantico local na extensao VS Code. + +Esta decisao ALSO locks que: + +1. `completion`, `hover` e `signature help` MUST nascer sobre uma mesma base editorial compiler-backed; +2. o LSP MUST ser o owner operacional da assistencia editorial; +3. a extensao VS Code MUST atuar apenas como cliente/adaptador do protocolo, e MUST NOT reconstruir semantica propria para simbolos, members ou assinaturas; +4. heuristicas locais no LSP MAY existir apenas como complemento temporario e estritamente limitado para lacunas nao resolvidas, mas MUST NOT virar uma segunda semantica canônica; +5. `go to definition`, formatter, identacao automatica robusta, quick fixes, `references`, `rename` e code actions amplas MUST ficar fora desta wave. + +## Rationale + +As tres features desta wave respondem essencialmente ao mesmo conjunto de perguntas: + +1. que simbolo eh este? +2. quais members ele expõe? +3. qual assinatura ele tem? +4. de onde ele vem? + +Implementa-las por caminhos tecnicos diferentes introduziria: + +1. duplicacao entre parser local, heuristicas e linking; +2. incoerencia entre o que aparece em `completion`, `hover` e `signature help`; +3. retrabalho na wave seguinte. + +Portanto, a primeira entrega precisa nascer sobre uma base editorial unificada, reaproveitando o que o compiler e o frontend PBS ja sabem sobre: + +1. escopo local; +2. imports e aliases; +3. stdlib; +4. builtin types; +5. services, hosts, structs, enums, constructors, functions e methods. + +## Technical Specification + +### 1. Shared Editorial Resolution Surface + +`compiler/pbs` e `studio/lsp` MUST introduzir uma superficie editorial resolvida comum para uso de `completion`, `hover` e `signature help`. + +Essa superficie MUST ser capaz de responder, de forma compiler-backed: + +1. identidade do simbolo; +2. `kind` do simbolo; +3. modulo/origem quando relevante; +4. assinatura ou shape quando aplicavel; +5. members disponíveis para receivers reconhecidos; +6. documentacao opcional quando existir, sem bloquear esta wave. + +Essa superficie MAY ser exposta por novos modelos internos do compiler, novos adapters no bridge do LSP, ou ambos. +Mas ela MUST permanecer derivada do compiler e MUST NOT ser reautoriada na extensao. + +### 2. Completion Scope + +`completion` MUST ser entregue como superfície minima utilizavel. + +Na wave 1, isso MUST cobrir pelo menos: + +1. keywords da linguagem; +2. nomes locais em escopo; +3. simbolos importados/publicos relevantes; +4. members apos `.` para superfícies reconhecidas, incluindo `service`, `host`, `builtin type`, `struct`, e call surfaces relacionadas. + +`completion` SHOULD expor labels, kinds e detalhes coerentes com a mesma base usada por `hover`. + +`completion` MUST NOT depender de tabela hardcoded na extensao para stdlib ou members de PBS. + +### 3. Hover Scope + +`hover` MUST deixar de ser placeholder e passar a ser simbolo-resolved. + +Na wave 1, o hover MUST incluir quando disponivel: + +1. `kind` do simbolo; +2. assinatura quando aplicavel; +3. modulo/origem quando relevante; +4. tipo ou shape basico quando isso existir de forma confiavel. + +`hover` MAY incluir documentacao textual opcional. +Mas a autoria de documentacao em PBS, incluindo eventual anotacao como `Document(...)`, MUST seguir discussao separada e MUST NOT bloquear esta wave. + +### 4. Signature Help Scope + +`signature help` MUST ser implementado para chamadas de: + +1. funcao; +2. metodo; +3. construtor. + +Na wave 1, ele MUST informar: + +1. a assinatura ativa; +2. o parametro ativo; +3. labels coerentes com a mesma representacao de assinatura usada no hover. + +`signature help` MUST usar a mesma base editorial de resolucao usada por `completion` e `hover`. + +### 5. Boundary Responsibilities + +`compiler/pbs`: + +1. MUST continuar sendo a fonte de verdade de semantica, linking e metadata relevante para simbolos e call surfaces; +2. MUST fornecer a base necessaria para resolucao editorial de simbolos, members e assinaturas. + +`studio/lsp`: + +1. MUST projetar essa base editorial em endpoints/protocol features adequados; +2. MUST anunciar as capabilities LSP necessarias para `completion`, `hover` e `signature help`; +3. MUST manter o transporte fiel ao modelo compiler-backed. + +`tools/vscode-extension`: + +1. MUST consumir o protocolo como cliente; +2. MUST NOT carregar tabelas paralelas de membros, stdlib ou assinaturas como fonte principal; +3. MAY conter apenas a logica estrutural normal de integração exigida pelo VS Code. + +### 6. Documentation Preparation Rule + +Esta wave MUST preparar um campo ou superfície opcional para documentacao editorial resolvida por simbolo. + +Mas esta decisao ALSO locks que: + +1. a surface de autoria dessa documentacao em PBS nao faz parte desta wave; +2. a sintaxe ou contrato de linguagem para documentacao authored deve ser discutido separadamente; +3. a ausencia dessa autoria nao bloqueia `completion`, `hover` nem `signature help` da wave 1. + +### 7. Explicit Non-Goals + +Esta decisao MUST NOT: + +1. incluir formatter completo; +2. incluir identacao automatica robusta de documento; +3. incluir `go to definition`; +4. incluir `references`; +5. incluir `rename`; +6. incluir quick fixes; +7. incluir code actions mais amplas; +8. definir o modelo de autoria de documentacao em PBS. + +## Constraints + +1. A wave 1 MUST priorizar coerencia entre `completion`, `hover` e `signature help` sobre cobertura enciclopedica de todos os casos. +2. A extensao VS Code MUST permanecer thin; a inteligencia editorial MUST ficar no compiler/LSP. +3. A implementacao MUST favorecer evolucao futura para `definition`, `references`, `documentation`, e outras editor features sem exigir reescrita conceitual da base editorial. +4. A implementacao MUST evitar surfaces duplicadas para stdlib, aliases, members e signatures. +5. Qualquer plan derivado desta decisao MUST separar claramente: + - base editorial compiler-backed; + - projeção LSP/protocolo; + - integração VS Code. + +## Revision Log + +- 2026-05-08: Initial draft from AGD-0038. +- 2026-05-08: Accepted and decomposed into PLN-0075, PLN-0076, and PLN-0077. diff --git a/discussion/workflow/plans/PLN-0075-pbs-editorial-resolution-surface-for-symbols-members-and-signatures.md b/discussion/workflow/plans/PLN-0075-pbs-editorial-resolution-surface-for-symbols-members-and-signatures.md new file mode 100644 index 00000000..de592972 --- /dev/null +++ b/discussion/workflow/plans/PLN-0075-pbs-editorial-resolution-surface-for-symbols-members-and-signatures.md @@ -0,0 +1,135 @@ +--- +id: PLN-0075 +ticket: pbs-lsp-editor-assistance-wave-1 +title: PBS Editorial Resolution Surface for Symbols, Members, and Signatures +status: open +created: 2026-05-08 +completed: +tags: [compiler, compiler-pbs, editor, completion, hover, signature-help, semantics] +--- + +## Objective + +Introduce a compiler-backed editorial resolution surface in `compiler/pbs` that can answer symbol identity, kind, origin, signature/shape, callable details, and receiver members for use by LSP `completion`, `hover`, and `signature help`. + +## Background + +`DEC-0035` requires all three editor-assistance features to be built over one shared compiler-backed base. The current repository already has useful pieces: + +- parser and AST for PBS; +- semantic validation and flow analysis; +- stdlib and import visibility rules; +- semantic token classification; +- builder-pipeline overlay analysis. + +What is still missing is an explicit editorial surface designed for interactive symbol resolution instead of only diagnostics or coloring. + +## Scope + +### Included + +- Define internal compiler-side models for editorial symbol resolution. +- Resolve local names, imported/public symbols, and recognized member surfaces. +- Resolve callable signatures for functions, methods, and constructors. +- Provide optional documentation slot(s) in the model without defining authored PBS documentation syntax. +- Add PBS-focused tests for symbol/member/signature resolution. + +### Excluded + +- LSP protocol capability changes. +- VS Code client behavior. +- Authored documentation syntax such as `Document(...)`. +- `go to definition`, `references`, `rename`, formatter, or code actions. + +## Non-Goals + +- Rebuilding the full compiler around IDE concerns. +- Solving every ambiguous or partial parse state in wave 1. +- Designing a generic multi-language IDE framework before PBS proves the model. + +## Execution Steps + +### Step 1 - Define editorial resolution models in compiler-owned surfaces + +**What:** Introduce explicit models for resolved symbols, member candidates, callable signatures, and optional documentation payload. +**How:** Add compiler-owned DTO/model types that can express: + +1. symbol identity and kind; +2. declared/imported origin; +3. callable label/signature shape; +4. receiver member entries; +5. optional documentation text field. + +The model must be expressive enough for `completion`, `hover`, and `signature help` without forcing each consumer to reinterpret raw AST nodes. +**File(s):** `prometeu-compiler/prometeu-compiler-core/src/main/java/**` and/or `prometeu-compiler/frontends/prometeu-frontend-pbs/src/main/java/**` depending on final ownership split. + +### Step 2 - Build PBS symbol resolution for local and imported surfaces + +**What:** Resolve names in editorial contexts. +**How:** Reuse parser, name/linking, stdlib import knowledge, and any existing semantic tables to resolve: + +1. local bindings in scope; +2. declared top-level PBS symbols; +3. imported/public symbols and aliases; +4. stdlib-owned surfaces currently recognized by the frontend. + +The implementation must avoid duplicating semantic truth already present in compiler/linking logic. +**File(s):** `prometeu-compiler/frontends/prometeu-frontend-pbs/src/main/java/p/studio/compiler/**`. + +### Step 3 - Build member and callable resolution + +**What:** Resolve members and callable signatures for recognized receiver and call surfaces. +**How:** Support at minimum: + +1. member lookup after `.` for services, hosts, builtin types, and structs; +2. direct callable lookup for functions and constructors; +3. active-call signature resolution for later `signature help` use. + +This step must produce stable labels/details that can be reused unchanged by LSP features. +**File(s):** `prometeu-compiler/frontends/prometeu-frontend-pbs/src/main/java/p/studio/compiler/**`. + +### Step 4 - Add editorial conformance tests + +**What:** Lock the compiler-backed editorial contract before LSP integration. +**How:** Add tests for: + +1. local variable and parameter resolution; +2. imported service/host/builtin-type resolution; +3. member lookup after `.` on recognized surfaces; +4. callable signature extraction for function/method/constructor cases; +5. optional documentation field stability when absent. + +**File(s):** PBS/compiler test suites under `prometeu-compiler/**/src/test/java/**`. + +## Test Requirements + +### Unit Tests + +- Model invariants for symbol/member/signature payloads. +- Resolver tests covering locals, imports, aliases, members, and constructors. + +### Integration Tests + +- Compiler-backed overlay/editorial tests using representative PBS snippets and stdlib imports. + +### Manual Verification + +- Inspect resolved payloads in tests or debug output and confirm they are sufficient to drive all three editor features without ad hoc reinterpretation. + +## Acceptance Criteria + +- [ ] Compiler-side editorial models exist for symbols, members, signatures, and optional documentation. +- [ ] PBS can resolve local names, imported/public symbols, and recognized member surfaces. +- [ ] Function, method, and constructor signatures are available through the shared editorial surface. +- [ ] No consumer is required to reconstruct signature/member meaning from raw AST-only data. + +## Dependencies + +- `DEC-0035` accepted and normatively locked. +- Existing PBS semantic and import/linking infrastructure remains the truth source. + +## Risks + +- Overfitting the first resolver to the current stdlib shape may hurt future fronts or future PBS growth. +- Mixing diagnostics-only semantics with editorial semantics carelessly may produce partial or contradictory answers. +- Incomplete member resolution can make `completion` appear flaky even if `hover` works. diff --git a/discussion/workflow/plans/PLN-0076-lsp-completion-hover-and-signature-help-over-editorial-resolution.md b/discussion/workflow/plans/PLN-0076-lsp-completion-hover-and-signature-help-over-editorial-resolution.md new file mode 100644 index 00000000..064f7d7d --- /dev/null +++ b/discussion/workflow/plans/PLN-0076-lsp-completion-hover-and-signature-help-over-editorial-resolution.md @@ -0,0 +1,121 @@ +--- +id: PLN-0076 +ticket: pbs-lsp-editor-assistance-wave-1 +title: LSP Completion, Hover, and Signature Help over Editorial Resolution +status: open +created: 2026-05-08 +completed: +tags: [studio, lsp, protocol, completion, hover, signature-help, editor] +--- + +## Objective + +Expose `completion`, real `hover`, and `signature help` through the project-scoped LSP stack by projecting the compiler-backed editorial resolution surface into explicit protocol capabilities and request handlers. + +## Background + +`DEC-0035` requires `studio/lsp` to be the operational owner of these editor features while remaining faithful to compiler-backed symbol, member, and signature resolution. The current LSP path only handles diagnostics, semantic tokens, and a placeholder hover. + +## Scope + +### Included + +- Extend the internal bridge/API with completion and signature-help operations. +- Replace placeholder hover with symbol-resolved hover. +- Announce LSP capabilities for completion and signature help. +- Add message models/mappers/tests for the new request/response paths. + +### Excluded + +- Creation of the underlying compiler editorial model itself. +- Authored documentation syntax. +- VS Code-specific UI behavior beyond normal LSP consumption. + +## Non-Goals + +- `go to definition`, `references`, `rename`, formatter, code actions, or quick fixes. +- Rich workspace-wide indexing beyond what the shared editorial surface already provides. + +## Execution Steps + +### Step 1 - Extend the LSP bridge contract + +**What:** Add compiler-backed editor-assistance operations to the bridge. +**How:** Evolve `LanguageServiceBridge` and related internal messages to support at minimum: + +1. completion requests; +2. symbol-resolved hover payloads; +3. signature-help requests. + +The bridge contract must align structurally with the shared editorial resolution surface rather than inventing a second feature-specific abstraction. +**File(s):** `prometeu-lsp/prometeu-lsp-v1/src/main/java/p/studio/lsp/services/**`, `prometeu-lsp/prometeu-lsp-v1/src/main/java/p/studio/lsp/messages/**`. + +### Step 2 - Implement compiler-backed request handling + +**What:** Wire LSP requests to compiler-backed editorial resolution. +**How:** Update `CompilerLanguageServiceBridge` so it: + +1. resolves completion candidates from local/import/member contexts; +2. resolves hover payloads from symbol identity, origin, and signatures; +3. resolves active call signatures for `signature help`. + +This step must remove the current fixed hover placeholder. +**File(s):** `prometeu-lsp/prometeu-lsp-v1/src/main/java/p/studio/lsp/services/compiler/**`. + +### Step 3 - Announce and map protocol capabilities + +**What:** Make the server advertise the new feature set and map payloads into lsp4j types. +**How:** Update protocol mappers and text-document service so the server announces: + +1. `completionProvider`; +2. `signatureHelpProvider`; +3. improved `hoverProvider` backed by real payloads. + +Map completion items, hover markdown, and signature-help structures into concrete LSP responses. +**File(s):** `prometeu-lsp/prometeu-lsp-v1/src/main/java/p/studio/lsp/services/protocol/**`, `.../mapping/**`. + +### Step 4 - Add transport and conformance tests + +**What:** Prevent regression to placeholder/editor-local behavior. +**How:** Add tests that verify: + +1. capabilities are announced correctly; +2. completion returns compiler-backed candidates; +3. hover no longer returns the baseline placeholder; +4. signature-help returns deterministic active-signature information. + +**File(s):** `prometeu-lsp/prometeu-lsp-v1/src/test/java/**`. + +## Test Requirements + +### Unit Tests + +- DTO/model invariants for completion, hover, and signature-help payloads. +- Mapper tests for lsp4j conversion. + +### Integration Tests + +- LSP request/response tests using realistic PBS snippets with locals, imports, and member access. + +### Manual Verification + +- Connect the VS Code extension and confirm server capabilities include completion and signature help. +- Confirm hover content changes with the hovered symbol rather than returning static baseline text. + +## Acceptance Criteria + +- [ ] The LSP bridge exposes completion and signature-help operations in addition to diagnostics, hover, and semantic tokens. +- [ ] Hover is symbol-resolved and no longer hardcoded placeholder text. +- [ ] The server advertises completion and signature-help capabilities. +- [ ] Completion, hover, and signature help all derive from the same compiler-backed editorial surface. + +## Dependencies + +- `DEC-0035` accepted and normatively locked. +- `PLN-0075` for the shared compiler-backed editorial resolution surface. + +## Risks + +- Protocol mapping can drift from compiler payload shape if feature-specific shortcuts are added. +- Active parameter/signature calculation may be brittle around incomplete syntax unless request handling is conservative. +- Completion can feel noisy if candidate ranking or filtering is too weak in wave 1. diff --git a/discussion/workflow/plans/PLN-0077-vscode-consumption-and-wave-1-editor-assistance-validation.md b/discussion/workflow/plans/PLN-0077-vscode-consumption-and-wave-1-editor-assistance-validation.md new file mode 100644 index 00000000..5dfd483c --- /dev/null +++ b/discussion/workflow/plans/PLN-0077-vscode-consumption-and-wave-1-editor-assistance-validation.md @@ -0,0 +1,103 @@ +--- +id: PLN-0077 +ticket: pbs-lsp-editor-assistance-wave-1 +title: VS Code Consumption and Wave 1 Editor Assistance Validation +status: open +created: 2026-05-08 +completed: +tags: [vscode, extension, editor, completion, hover, signature-help, validation] +--- + +## Objective + +Keep the VS Code extension thin while validating that the new LSP-delivered `completion`, `hover`, and `signature help` features actually produce a minimally usable PBS editing experience end to end. + +## Background + +`DEC-0035` explicitly requires the extension to remain a client/adaptor rather than a second semantic engine. Because VS Code already knows how to consume LSP completion, hover, and signature-help responses, the extension work should be small and mostly about ensuring transport, configuration, and real validation are correct. + +## Scope + +### Included + +- Confirm the extension does not need or gain local semantic tables for stdlib, members, or signatures. +- Adjust only the minimal extension/bootstrap behavior needed for the new LSP features to flow correctly. +- Add verification coverage and manual validation guidance for the full wave. + +### Excluded + +- Compiler-side editorial resolution logic. +- LSP-side protocol feature implementation. +- Formatter/indentation, code actions, or non-wave-1 IDE features. + +## Non-Goals + +- Turning the extension into a feature-rich semantic client. +- Adding hardcoded completion/signature content for PBS inside TypeScript runtime code. + +## Execution Steps + +### Step 1 - Verify thin-client integration boundaries + +**What:** Confirm the extension remains a pure LSP consumer for the new features. +**How:** Review and adjust the extension only where necessary so completion, hover, and signature help are obtained from the LSP session without client-side semantic fallback tables. +**File(s):** `tools/vscode-extension/src/**`, `tools/vscode-extension/package.json`. + +### Step 2 - Add any minimal structural configuration required by VS Code + +**What:** Keep static contribution surfaces minimal and structural. +**How:** If VS Code requires additional structural contribution metadata for the new features, add only that metadata. Do not add curated PBS semantic or signature data into the extension package. +**File(s):** `tools/vscode-extension/package.json`. + +### Step 3 - Add validation coverage for end-to-end editor assistance + +**What:** Lock the no-local-semantics rule and the end-to-end feature expectations. +**How:** Add tests or deterministic verification steps that ensure: + +1. the extension connects and receives the feature set from the server; +2. no local completion/signature tables were introduced; +3. the user-facing wave can be exercised end to end. + +**File(s):** `tools/vscode-extension/**`, existing validation harnesses if present, and related docs/test notes. + +### Step 4 - Define manual smoke scenarios for wave 1 usability + +**What:** Make the wave verifiable as a product experience rather than only a protocol exercise. +**How:** Document and run manual checks for: + +1. keyword and local-name completion; +2. imported stdlib/member completion after `.`; +3. hover on locals, imported services, builtin types, and methods; +4. signature help during function/method/constructor calls. + +**File(s):** extension verification notes or adjacent implementation docs/tests as appropriate. + +## Test Requirements + +### Unit Tests + +- Any extension-side helpers introduced for structural integration only. + +### Integration Tests + +- End-to-end or near-end-to-end validation that VS Code consumes the server feature set without local semantic duplication. + +### Manual Verification + +- Open representative PBS files in VS Code and verify `completion`, `hover`, and `signature help` behavior matches the expected wave-1 scope. + +## Acceptance Criteria + +- [ ] The extension remains thin and contains no new hardcoded PBS semantic tables for members or signatures. +- [ ] VS Code can consume the new LSP completion, hover, and signature-help responses without extension-side semantic authorship. +- [ ] Wave-1 smoke scenarios are documented and manually verifiable. + +## Dependencies + +- `DEC-0035` accepted and normatively locked. +- `PLN-0076` for the actual LSP feature delivery. + +## Risks + +- It is easy to accidentally patch around server gaps with client-local logic; this plan must resist that. +- Validation can become too protocol-centric and miss real usability failures if manual smoke scenarios are weak. -- 2.47.2 From 7f40541e965cf1c0632acb441be1764e5a23493c Mon Sep 17 00:00:00 2001 From: bQUARKz Date: Fri, 8 May 2026 10:04:39 +0100 Subject: [PATCH 34/37] implements PLN-0075 --- .../PbsEditorialCompletionCandidate.java | 30 + .../semantics/PbsEditorialResolvedSymbol.java | 35 + .../pbs/semantics/PbsEditorialSignature.java | 27 + .../semantics/PbsEditorialSignatureHelp.java | 22 + .../semantics/PbsEditorialSupportService.java | 1303 +++++++++++++++++ .../pbs/semantics/PbsEditorialSymbolKind.java | 21 + .../pbs/semantics/PbsFlowSemanticSupport.java | 4 + .../services/PBSFrontendPhaseService.java | 4 + .../PbsEditorialSupportServiceTest.java | 215 +++ 9 files changed, 1661 insertions(+) create mode 100644 prometeu-compiler/frontends/prometeu-frontend-pbs/src/main/java/p/studio/compiler/pbs/semantics/PbsEditorialCompletionCandidate.java create mode 100644 prometeu-compiler/frontends/prometeu-frontend-pbs/src/main/java/p/studio/compiler/pbs/semantics/PbsEditorialResolvedSymbol.java create mode 100644 prometeu-compiler/frontends/prometeu-frontend-pbs/src/main/java/p/studio/compiler/pbs/semantics/PbsEditorialSignature.java create mode 100644 prometeu-compiler/frontends/prometeu-frontend-pbs/src/main/java/p/studio/compiler/pbs/semantics/PbsEditorialSignatureHelp.java create mode 100644 prometeu-compiler/frontends/prometeu-frontend-pbs/src/main/java/p/studio/compiler/pbs/semantics/PbsEditorialSupportService.java create mode 100644 prometeu-compiler/frontends/prometeu-frontend-pbs/src/main/java/p/studio/compiler/pbs/semantics/PbsEditorialSymbolKind.java create mode 100644 prometeu-compiler/frontends/prometeu-frontend-pbs/src/test/java/p/studio/compiler/pbs/semantics/PbsEditorialSupportServiceTest.java diff --git a/prometeu-compiler/frontends/prometeu-frontend-pbs/src/main/java/p/studio/compiler/pbs/semantics/PbsEditorialCompletionCandidate.java b/prometeu-compiler/frontends/prometeu-frontend-pbs/src/main/java/p/studio/compiler/pbs/semantics/PbsEditorialCompletionCandidate.java new file mode 100644 index 00000000..4001004b --- /dev/null +++ b/prometeu-compiler/frontends/prometeu-frontend-pbs/src/main/java/p/studio/compiler/pbs/semantics/PbsEditorialCompletionCandidate.java @@ -0,0 +1,30 @@ +package p.studio.compiler.pbs.semantics; + +import java.util.Objects; + +public record PbsEditorialCompletionCandidate( + String label, + PbsEditorialSymbolKind kind, + String detail, + String origin) { + public PbsEditorialCompletionCandidate { + label = requireText(label, "label"); + kind = Objects.requireNonNull(kind, "kind"); + detail = normalize(detail); + origin = normalize(origin); + } + + private static String requireText( + final String value, + final String field) { + final String candidate = normalize(value); + if (candidate.isEmpty()) { + throw new IllegalArgumentException(field + " must not be blank"); + } + return candidate; + } + + private static String normalize(final String value) { + return value == null ? "" : value.trim(); + } +} diff --git a/prometeu-compiler/frontends/prometeu-frontend-pbs/src/main/java/p/studio/compiler/pbs/semantics/PbsEditorialResolvedSymbol.java b/prometeu-compiler/frontends/prometeu-frontend-pbs/src/main/java/p/studio/compiler/pbs/semantics/PbsEditorialResolvedSymbol.java new file mode 100644 index 00000000..43abee2b --- /dev/null +++ b/prometeu-compiler/frontends/prometeu-frontend-pbs/src/main/java/p/studio/compiler/pbs/semantics/PbsEditorialResolvedSymbol.java @@ -0,0 +1,35 @@ +package p.studio.compiler.pbs.semantics; + +import java.util.List; +import java.util.Objects; + +public record PbsEditorialResolvedSymbol( + String displayName, + PbsEditorialSymbolKind kind, + String detail, + String origin, + List signatures, + String documentation) { + public PbsEditorialResolvedSymbol { + displayName = requireText(displayName, "displayName"); + kind = Objects.requireNonNull(kind, "kind"); + detail = normalize(detail); + origin = normalize(origin); + signatures = List.copyOf(Objects.requireNonNull(signatures, "signatures")); + documentation = normalize(documentation); + } + + private static String requireText( + final String value, + final String field) { + final String candidate = normalize(value); + if (candidate.isEmpty()) { + throw new IllegalArgumentException(field + " must not be blank"); + } + return candidate; + } + + private static String normalize(final String value) { + return value == null ? "" : value.trim(); + } +} diff --git a/prometeu-compiler/frontends/prometeu-frontend-pbs/src/main/java/p/studio/compiler/pbs/semantics/PbsEditorialSignature.java b/prometeu-compiler/frontends/prometeu-frontend-pbs/src/main/java/p/studio/compiler/pbs/semantics/PbsEditorialSignature.java new file mode 100644 index 00000000..43bb9a89 --- /dev/null +++ b/prometeu-compiler/frontends/prometeu-frontend-pbs/src/main/java/p/studio/compiler/pbs/semantics/PbsEditorialSignature.java @@ -0,0 +1,27 @@ +package p.studio.compiler.pbs.semantics; + +import java.util.List; +import java.util.Objects; + +public record PbsEditorialSignature( + String callableName, + String label, + List parameterLabels, + String returnLabel) { + public PbsEditorialSignature { + callableName = requireText(callableName, "callableName"); + label = requireText(label, "label"); + parameterLabels = List.copyOf(Objects.requireNonNull(parameterLabels, "parameterLabels")); + returnLabel = requireText(returnLabel, "returnLabel"); + } + + private static String requireText( + final String value, + final String field) { + final String candidate = Objects.requireNonNull(value, field).trim(); + if (candidate.isEmpty()) { + throw new IllegalArgumentException(field + " must not be blank"); + } + return candidate; + } +} diff --git a/prometeu-compiler/frontends/prometeu-frontend-pbs/src/main/java/p/studio/compiler/pbs/semantics/PbsEditorialSignatureHelp.java b/prometeu-compiler/frontends/prometeu-frontend-pbs/src/main/java/p/studio/compiler/pbs/semantics/PbsEditorialSignatureHelp.java new file mode 100644 index 00000000..e632e2ed --- /dev/null +++ b/prometeu-compiler/frontends/prometeu-frontend-pbs/src/main/java/p/studio/compiler/pbs/semantics/PbsEditorialSignatureHelp.java @@ -0,0 +1,22 @@ +package p.studio.compiler.pbs.semantics; + +import java.util.List; +import java.util.Objects; + +public record PbsEditorialSignatureHelp( + List signatures, + int activeSignature, + int activeParameter) { + public PbsEditorialSignatureHelp { + signatures = List.copyOf(Objects.requireNonNull(signatures, "signatures")); + if (signatures.isEmpty()) { + throw new IllegalArgumentException("signatures must not be empty"); + } + if (activeSignature < 0 || activeSignature >= signatures.size()) { + throw new IllegalArgumentException("activeSignature must reference one of the provided signatures"); + } + if (activeParameter < 0) { + throw new IllegalArgumentException("activeParameter must be >= 0"); + } + } +} diff --git a/prometeu-compiler/frontends/prometeu-frontend-pbs/src/main/java/p/studio/compiler/pbs/semantics/PbsEditorialSupportService.java b/prometeu-compiler/frontends/prometeu-frontend-pbs/src/main/java/p/studio/compiler/pbs/semantics/PbsEditorialSupportService.java new file mode 100644 index 00000000..dc4c839c --- /dev/null +++ b/prometeu-compiler/frontends/prometeu-frontend-pbs/src/main/java/p/studio/compiler/pbs/semantics/PbsEditorialSupportService.java @@ -0,0 +1,1303 @@ +package p.studio.compiler.pbs.semantics; + +import p.studio.compiler.messages.FESurfaceContext; +import p.studio.compiler.pbs.ast.PbsAst; +import p.studio.compiler.pbs.lexer.PbsLexer; +import p.studio.compiler.pbs.lexer.PbsToken; +import p.studio.compiler.pbs.lexer.PbsTokenKind; +import p.studio.compiler.source.Span; +import p.studio.compiler.source.diagnostics.DiagnosticSink; +import p.studio.compiler.source.identifiers.FileId; +import p.studio.utilities.structures.ReadOnlyList; + +import java.util.*; + +import static p.studio.compiler.pbs.semantics.PbsFlowSemanticSupport.*; + +public final class PbsEditorialSupportService { + private static final Set BUILTIN_TYPE_NAMES = Set.of("int", "float", "bool", "str", "string", "i32", "i64", "f32", "f64"); + private static final List KEYWORDS = List.of( + "fn", "declare", "let", "const", "global", "struct", "service", "host", "contract", "enum", "error", "callback", + "if", "else", "switch", "for", "until", "step", "while", "break", "continue", "return", + "new", "bind", "apply", "handle", "some", "none", "ok", "err", "true", "false"); + + public List completion( + final String sourceText, + final PbsAst.File ast, + final ReadOnlyList supplementalTopDecls, + final int offset) { + return completion(sourceText, ast, supplementalTopDecls, FESurfaceContext.empty(), offset); + } + + public List completion( + final String sourceText, + final PbsAst.File ast, + final ReadOnlyList supplementalTopDecls, + final FESurfaceContext feSurfaceContext, + final int offset) { + final var context = buildContext(sourceText, ast, supplementalTopDecls, feSurfaceContext); + final var scopeState = context.scopeStateAt(offset); + final Integer previousTokenIndex = context.previousSignificantTokenIndexAt(offset); + if (previousTokenIndex != null && context.token(previousTokenIndex).kind() == PbsTokenKind.DOT) { + final TypeView receiverType = context.resolveReceiverTypeBeforeDot(previousTokenIndex, scopeState); + return context.memberCompletions(receiverType); + } + return context.generalCompletions(scopeState); + } + + public Optional hover( + final String sourceText, + final PbsAst.File ast, + final ReadOnlyList supplementalTopDecls, + final int offset) { + return hover(sourceText, ast, supplementalTopDecls, FESurfaceContext.empty(), offset); + } + + public Optional hover( + final String sourceText, + final PbsAst.File ast, + final ReadOnlyList supplementalTopDecls, + final FESurfaceContext feSurfaceContext, + final int offset) { + final var context = buildContext(sourceText, ast, supplementalTopDecls, feSurfaceContext); + final Integer tokenIndex = context.identifierTokenIndexAt(offset); + if (tokenIndex == null) { + return Optional.empty(); + } + final var scopeState = context.scopeStateAt(offset); + final var token = context.token(tokenIndex); + final Integer previousTokenIndex = context.previousSignificantTokenIndex(tokenIndex); + if (previousTokenIndex != null && context.token(previousTokenIndex).kind() == PbsTokenKind.DOT) { + final TypeView receiverType = context.resolveReceiverTypeBeforeDot(previousTokenIndex, scopeState); + return context.resolveMemberHover(receiverType, token.lexeme()); + } + return context.resolveSymbolHover(token.lexeme(), tokenIndex, scopeState); + } + + public Optional signatureHelp( + final String sourceText, + final PbsAst.File ast, + final ReadOnlyList supplementalTopDecls, + final int offset) { + return signatureHelp(sourceText, ast, supplementalTopDecls, FESurfaceContext.empty(), offset); + } + + public Optional signatureHelp( + final String sourceText, + final PbsAst.File ast, + final ReadOnlyList supplementalTopDecls, + final FESurfaceContext feSurfaceContext, + final int offset) { + final var context = buildContext(sourceText, ast, supplementalTopDecls, feSurfaceContext); + final var callSite = context.callSiteAt(offset); + if (callSite == null) { + return Optional.empty(); + } + final var scopeState = context.scopeStateAt(offset); + final List signatures = switch (callSite.kind()) { + case FUNCTION -> context.resolveCallableSignatures(callSite.name(), scopeState); + case MEMBER -> { + final TypeView receiverType = context.resolveReceiverTypeBeforeDot(callSite.memberDotTokenIndex(), scopeState); + yield context.resolveMemberSignatures(receiverType, callSite.name()); + } + case CONSTRUCTOR -> context.resolveConstructorSignatures(callSite.name()); + }; + if (signatures.isEmpty()) { + return Optional.empty(); + } + return Optional.of(new PbsEditorialSignatureHelp(signatures, 0, callSite.activeParameter())); + } + + private DocumentContext buildContext( + final String sourceText, + final PbsAst.File ast, + final ReadOnlyList supplementalTopDecls, + final FESurfaceContext feSurfaceContext) { + return new DocumentContext(sourceText, ast, supplementalTopDecls, feSurfaceContext); + } + + private static final class DocumentContext { + private final String sourceText; + private final PbsAst.File ast; + private final ReadOnlyList editorialSupplementalTopDecls; + private final ReadOnlyList tokens; + private final Model model; + private final PbsFlowTypeOps typeOps = new PbsFlowTypeOps(); + private final PbsFlowExpressionAnalyzer expressionAnalyzer = new PbsFlowExpressionAnalyzer(typeOps); + private final PbsInlineHintSurfaceFormatter typeFormatter = new PbsInlineHintSurfaceFormatter(); + private final Map topLevelSymbols; + private final Map importedSymbols; + private final Map supplementalSymbols; + private final Map aliasedTypeRefs; + + private DocumentContext( + final String sourceText, + final PbsAst.File ast, + final ReadOnlyList supplementalTopDecls, + final FESurfaceContext feSurfaceContext) { + this.sourceText = sourceText == null ? "" : sourceText; + this.ast = Objects.requireNonNull(ast, "ast"); + final ArrayList expandedSupplementals = new ArrayList<>(supplementalTopDecls == null + ? List.of() + : supplementalTopDecls.asList()); + this.importedSymbols = buildImportedSymbols(expandedSupplementals); + this.editorialSupplementalTopDecls = ReadOnlyList.wrap(expandedSupplementals); + this.tokens = PbsLexer.lex(this.sourceText, FileId.none(), DiagnosticSink.empty()); + this.model = Model.from( + ast, + editorialSupplementalTopDecls, + feSurfaceContext == null ? FESurfaceContext.empty() : feSurfaceContext, + DiagnosticSink.empty()); + this.topLevelSymbols = buildTopLevelSymbols(); + this.supplementalSymbols = buildSupplementalSymbols(); + this.aliasedTypeRefs = buildAliasedTypeRefs(); + } + + private Map buildTopLevelSymbols() { + final Map symbols = new LinkedHashMap<>(); + for (final var topDecl : ast.topDecls()) { + final String name = topDeclName(topDecl); + if (name == null || symbols.containsKey(name)) { + continue; + } + symbols.put(name, new TopDeclSymbol(name, topDecl, "current module")); + } + return Map.copyOf(symbols); + } + + private Map buildImportedSymbols(final ArrayList expandedSupplementals) { + final Map symbols = new LinkedHashMap<>(); + for (final var importDecl : ast.imports()) { + final String moduleLabel = formatModuleRef(importDecl.moduleRef()); + for (final var item : importDecl.items()) { + final String localName = item.alias() == null || item.alias().isBlank() + ? item.name() + : item.alias(); + final PbsAst.TopDecl target = findSupplementalTopDecl(item.name(), expandedSupplementals); + if (target == null) { + continue; + } + symbols.put(localName, new TopDeclSymbol(localName, cloneTopDeclWithName(target, localName), moduleLabel)); + if (!localName.equals(item.name())) { + expandedSupplementals.add(cloneTopDeclWithName(target, localName)); + } + } + } + return Map.copyOf(symbols); + } + + private Map buildSupplementalSymbols() { + final Map symbols = new LinkedHashMap<>(); + for (final var topDecl : editorialSupplementalTopDecls) { + final String name = topDeclName(topDecl); + if (name == null || importedSymbols.containsKey(name) || symbols.containsKey(name)) { + continue; + } + symbols.put(name, new TopDeclSymbol(name, topDecl, "imported context")); + } + return Map.copyOf(symbols); + } + + private Map buildAliasedTypeRefs() { + final Map typeRefs = new HashMap<>(); + for (final var entry : importedSymbols.entrySet()) { + if (entry.getValue().decl() instanceof PbsAst.StructDecl structDecl) { + typeRefs.put(entry.getKey(), PbsAst.TypeRef.simple(structDecl.name(), structDecl.span())); + } else if (entry.getValue().decl() instanceof PbsAst.BuiltinTypeDecl builtinTypeDecl) { + typeRefs.put(entry.getKey(), PbsAst.TypeRef.simple(builtinTypeDecl.name(), builtinTypeDecl.span())); + } else if (entry.getValue().decl() instanceof PbsAst.ServiceDecl serviceDecl) { + typeRefs.put(entry.getKey(), PbsAst.TypeRef.simple(serviceDecl.name(), serviceDecl.span())); + } else if (entry.getValue().decl() instanceof PbsAst.HostDecl hostDecl) { + typeRefs.put(entry.getKey(), PbsAst.TypeRef.simple(hostDecl.name(), hostDecl.span())); + } else if (entry.getValue().decl() instanceof PbsAst.ContractDecl contractDecl) { + typeRefs.put(entry.getKey(), PbsAst.TypeRef.simple(contractDecl.name(), contractDecl.span())); + } else if (entry.getValue().decl() instanceof PbsAst.EnumDecl enumDecl) { + typeRefs.put(entry.getKey(), PbsAst.TypeRef.simple(enumDecl.name(), enumDecl.span())); + } else if (entry.getValue().decl() instanceof PbsAst.ErrorDecl errorDecl) { + typeRefs.put(entry.getKey(), PbsAst.TypeRef.simple(errorDecl.name(), errorDecl.span())); + } else if (entry.getValue().decl() instanceof PbsAst.CallbackDecl callbackDecl) { + typeRefs.put(entry.getKey(), PbsAst.TypeRef.simple(callbackDecl.name(), callbackDecl.span())); + } + } + return Map.copyOf(typeRefs); + } + + private ScopeState scopeStateAt(final int offset) { + final CallableFrame callableFrame = callableFrameAt(offset); + if (callableFrame == null) { + return new ScopeState(new Scope(), null, TypeView.unit(), null, Set.of()); + } + final Scope scope = new Scope(); + for (final var parameter : callableFrame.parameters()) { + scope.bind(parameter.name(), typeOps.typeFromTypeRef(parameter.typeRef(), model, callableFrame.receiverType()), true); + } + final Scope resolvedScope = populateScopeUntilOffset(callableFrame.body(), scope, callableFrame, offset); + return new ScopeState( + resolvedScope, + callableFrame.receiverType(), + callableFrame.returnType(), + callableFrame.resultErrorName(), + callableFrame.parameterNames()); + } + + private Scope populateScopeUntilOffset( + final PbsAst.Block block, + final Scope seedScope, + final CallableFrame frame, + final int offset) { + final Scope scope = seedScope.copy(); + for (final var statement : block.statements()) { + if (statement.span().getStart() >= offset) { + break; + } + if (statement.span().contains(offset)) { + if (statement instanceof PbsAst.IfStatement ifStatement) { + if (ifStatement.thenBlock().span().contains(offset)) { + return populateScopeUntilOffset(ifStatement.thenBlock(), scope, frame, offset); + } + if (ifStatement.elseBlock() != null && ifStatement.elseBlock().span().contains(offset)) { + return populateScopeUntilOffset(ifStatement.elseBlock(), scope, frame, offset); + } + if (ifStatement.elseIf() != null && ifStatement.elseIf().span().contains(offset)) { + final var nestedBlock = new PbsAst.Block(ReadOnlyList.wrap(List.of(ifStatement.elseIf())), null, ifStatement.elseIf().span()); + return populateScopeUntilOffset(nestedBlock, scope, frame, offset); + } + } else if (statement instanceof PbsAst.ForStatement forStatement) { + if (forStatement.body().span().contains(offset)) { + final Scope loopScope = scope.copy(); + loopScope.bind(forStatement.iteratorName(), typeOps.typeFromTypeRef(forStatement.iteratorType(), model, frame.receiverType())); + return populateScopeUntilOffset(forStatement.body(), loopScope, frame, offset); + } + } else if (statement instanceof PbsAst.WhileStatement whileStatement && whileStatement.body().span().contains(offset)) { + return populateScopeUntilOffset(whileStatement.body(), scope, frame, offset); + } + return scope; + } + applyStatementEffects(statement, scope, frame); + } + return scope; + } + + private void applyStatementEffects( + final PbsAst.Statement statement, + final Scope scope, + final CallableFrame frame) { + if (statement instanceof PbsAst.LetStatement letStatement) { + final PbsAst.TypeRef explicitType = aliasExpandedTypeRef(letStatement.explicitType()); + final TypeView expectedType = explicitType == null + ? null + : typeOps.typeFromTypeRef(explicitType, model, frame.receiverType()); + final TypeView inferredType = analyzeExpressionType( + letStatement.initializer(), + scope, + expectedType, + frame.returnType(), + frame.resultErrorName(), + frame.receiverType()); + final TypeView resolvedType = expectedType == null ? inferredType : expectedType; + scope.bind(letStatement.name(), resolvedType, !letStatement.isConst()); + } + } + + private TypeView analyzeExpressionType( + final PbsAst.Expression expression, + final Scope scope, + final TypeView expectedType, + final TypeView returnType, + final String resultErrorName, + final TypeView receiverType) { + return expressionAnalyzer.analyzeExpression( + expression, + scope, + expectedType, + returnType, + resultErrorName, + receiverType, + model, + DiagnosticSink.empty(), + ExprUse.VALUE, + true, + this::analyzeNestedBlock).type(); + } + + private TypeView analyzeNestedBlock( + final PbsAst.Block block, + final Scope outerScope, + final TypeView returnType, + final String resultErrorName, + final TypeView receiverType, + final Model ignoredModel, + final DiagnosticSink diagnostics, + final boolean valueContext) { + final Scope scoped = outerScope.copy(); + for (final var statement : block.statements()) { + if (statement instanceof PbsAst.LetStatement letStatement) { + final PbsAst.TypeRef explicitType = aliasExpandedTypeRef(letStatement.explicitType()); + final TypeView expectedType = explicitType == null + ? null + : typeOps.typeFromTypeRef(explicitType, model, receiverType); + final TypeView inferredType = expressionAnalyzer.analyzeExpression( + letStatement.initializer(), + scoped, + expectedType, + returnType, + resultErrorName, + receiverType, + model, + diagnostics, + ExprUse.VALUE, + true, + this::analyzeNestedBlock).type(); + scoped.bind(letStatement.name(), expectedType == null ? inferredType : expectedType, !letStatement.isConst()); + } + } + if (block.tailExpression() == null) { + return TypeView.unit(); + } + return expressionAnalyzer.analyzeExpression( + block.tailExpression(), + scoped, + null, + returnType, + resultErrorName, + receiverType, + model, + diagnostics, + ExprUse.VALUE, + valueContext, + this::analyzeNestedBlock).type(); + } + + private CallableFrame callableFrameAt(final int offset) { + for (final var topDecl : ast.topDecls()) { + if (topDecl instanceof PbsAst.FunctionDecl functionDecl && functionDecl.span().contains(offset)) { + return new CallableFrame( + functionDecl.parameters(), + functionDecl.body(), + null, + typeOps.callableReturnType( + functionDecl.returnKind(), + functionDecl.returnType(), + functionDecl.resultErrorType(), + model), + errorName(functionDecl.resultErrorType())); + } + if (topDecl instanceof PbsAst.StructDecl structDecl && structDecl.span().contains(offset)) { + final TypeView receiverType = TypeView.struct(structDecl.name()); + for (final var method : structDecl.methods()) { + if (method.span().contains(offset)) { + return new CallableFrame( + method.parameters(), + method.body(), + receiverType, + typeOps.callableReturnType( + method.returnKind(), + method.returnType(), + method.resultErrorType(), + model), + errorName(method.resultErrorType())); + } + } + for (final var ctor : structDecl.ctors()) { + if (ctor.span().contains(offset)) { + return new CallableFrame( + ctor.parameters(), + ctor.body(), + receiverType, + TypeView.unit(), + null); + } + } + } + if (topDecl instanceof PbsAst.ServiceDecl serviceDecl && serviceDecl.span().contains(offset)) { + final TypeView receiverType = TypeView.service(serviceDecl.name()); + for (final var method : serviceDecl.methods()) { + if (method.span().contains(offset)) { + return new CallableFrame( + method.parameters(), + method.body(), + receiverType, + typeOps.callableReturnType( + method.returnKind(), + method.returnType(), + method.resultErrorType(), + model), + errorName(method.resultErrorType())); + } + } + } + } + return null; + } + + private List generalCompletions(final ScopeState scopeState) { + final Map completions = new LinkedHashMap<>(); + for (final var keyword : KEYWORDS) { + completions.put(keyword, new PbsEditorialCompletionCandidate(keyword, PbsEditorialSymbolKind.KEYWORD, "", "")); + } + for (final var parameterName : scopeState.parameterNames()) { + final TypeView type = scopeState.scope().resolve(parameterName); + completions.put(parameterName, new PbsEditorialCompletionCandidate( + parameterName, + PbsEditorialSymbolKind.PARAMETER, + formatType(type), + "local parameter")); + } + for (final var entry : scopeState.scope().entries().entrySet()) { + if (scopeState.parameterNames().contains(entry.getKey())) { + continue; + } + completions.put(entry.getKey(), new PbsEditorialCompletionCandidate( + entry.getKey(), + PbsEditorialSymbolKind.LOCAL, + formatType(entry.getValue().type()), + entry.getValue().mutable() ? "local mutable binding" : "local const binding")); + } + for (final var entry : importedSymbols.entrySet()) { + completions.putIfAbsent(entry.getKey(), completionFromTopDecl(entry.getValue())); + } + for (final var entry : supplementalSymbols.entrySet()) { + completions.putIfAbsent(entry.getKey(), completionFromTopDecl(entry.getValue())); + } + for (final var entry : topLevelSymbols.entrySet()) { + completions.putIfAbsent(entry.getKey(), completionFromTopDecl(entry.getValue())); + } + return List.copyOf(completions.values()); + } + + private List memberCompletions(final TypeView receiverType) { + if (receiverType == null) { + return List.of(); + } + final Map completions = new LinkedHashMap<>(); + if (receiverType.kind() == Kind.STRUCT) { + final StructInfo structInfo = model.structs.get(receiverType.name()); + if (structInfo != null) { + for (final var field : structInfo.fields().entrySet()) { + completions.put(field.getKey(), new PbsEditorialCompletionCandidate( + field.getKey(), + PbsEditorialSymbolKind.FIELD, + formatType(field.getValue().type()), + receiverType.name())); + } + for (final var method : structInfo.methods().entrySet()) { + completions.put(method.getKey(), new PbsEditorialCompletionCandidate( + method.getKey(), + PbsEditorialSymbolKind.METHOD, + formatCallableDetails(method.getValue()), + receiverType.name())); + } + } + } else if (receiverType.kind() == Kind.SERVICE || receiverType.kind() == Kind.CONTRACT) { + final Map> methods = receiverType.kind() == Kind.SERVICE + ? Optional.ofNullable(model.services.get(receiverType.name())).map(ServiceInfo::methods).orElse(Map.of()) + : Optional.ofNullable(model.contracts.get(receiverType.name())).map(ContractInfo::methods).orElse(Map.of()); + for (final var method : methods.entrySet()) { + completions.put(method.getKey(), new PbsEditorialCompletionCandidate( + method.getKey(), + PbsEditorialSymbolKind.METHOD, + formatCallableDetails(method.getValue()), + receiverType.name())); + } + } + return List.copyOf(completions.values()); + } + + private Optional resolveSymbolHover( + final String symbolName, + final int tokenIndex, + final ScopeState scopeState) { + if (scopeState.parameterNames().contains(symbolName)) { + final TypeView type = scopeState.scope().resolve(symbolName); + return Optional.of(new PbsEditorialResolvedSymbol( + symbolName, + PbsEditorialSymbolKind.PARAMETER, + formatType(type), + "local parameter", + List.of(), + "")); + } + final Scope.LocalSymbol localSymbol = scopeState.scope().entries().get(symbolName); + if (localSymbol != null) { + return Optional.of(new PbsEditorialResolvedSymbol( + symbolName, + PbsEditorialSymbolKind.LOCAL, + formatType(localSymbol.type()), + localSymbol.mutable() ? "local mutable binding" : "local const binding", + List.of(), + "")); + } + final Integer previousTokenIndex = previousSignificantTokenIndex(tokenIndex); + if (previousTokenIndex != null && token(previousTokenIndex).kind() == PbsTokenKind.NEW) { + final TopDeclSymbol topDeclSymbol = resolveTopDeclSymbol(symbolName); + if (topDeclSymbol != null) { + return Optional.of(constructorSymbolFromTopDecl(topDeclSymbol, resolveConstructorSignatures(symbolName))); + } + } + final TopDeclSymbol importedSymbol = importedSymbols.get(symbolName); + if (importedSymbol != null) { + return Optional.of(symbolFromTopDecl(importedSymbol, signaturesForTopDecl(importedSymbol.decl()))); + } + final TopDeclSymbol supplementalSymbol = supplementalSymbols.get(symbolName); + if (supplementalSymbol != null) { + return Optional.of(symbolFromTopDecl(supplementalSymbol, signaturesForTopDecl(supplementalSymbol.decl()))); + } + final TopDeclSymbol topLevelSymbol = topLevelSymbols.get(symbolName); + if (topLevelSymbol != null) { + return Optional.of(symbolFromTopDecl(topLevelSymbol, signaturesForTopDecl(topLevelSymbol.decl()))); + } + if (BUILTIN_TYPE_NAMES.contains(symbolName)) { + return Optional.of(new PbsEditorialResolvedSymbol( + symbolName, + PbsEditorialSymbolKind.BUILTIN_TYPE, + "builtin scalar type", + "", + List.of(), + "")); + } + return Optional.empty(); + } + + private Optional resolveMemberHover( + final TypeView receiverType, + final String memberName) { + if (receiverType == null) { + return Optional.empty(); + } + if (receiverType.kind() == Kind.STRUCT) { + final StructInfo structInfo = model.structs.get(receiverType.name()); + if (structInfo == null) { + return Optional.empty(); + } + final StructFieldInfo field = structInfo.fields().get(memberName); + if (field != null) { + return Optional.of(new PbsEditorialResolvedSymbol( + memberName, + PbsEditorialSymbolKind.FIELD, + formatType(field.type()), + receiverType.name(), + List.of(), + "")); + } + final List methods = structInfo.methods().get(memberName); + if (methods != null && !methods.isEmpty()) { + return Optional.of(new PbsEditorialResolvedSymbol( + memberName, + PbsEditorialSymbolKind.METHOD, + formatCallableDetails(methods), + receiverType.name(), + signaturesFromCallables(methods), + "")); + } + } + if (receiverType.kind() == Kind.SERVICE || receiverType.kind() == Kind.CONTRACT) { + final Map> methods = receiverType.kind() == Kind.SERVICE + ? Optional.ofNullable(model.services.get(receiverType.name())).map(ServiceInfo::methods).orElse(Map.of()) + : Optional.ofNullable(model.contracts.get(receiverType.name())).map(ContractInfo::methods).orElse(Map.of()); + final List signatures = methods.get(memberName); + if (signatures != null && !signatures.isEmpty()) { + return Optional.of(new PbsEditorialResolvedSymbol( + memberName, + PbsEditorialSymbolKind.METHOD, + formatCallableDetails(signatures), + receiverType.name(), + signaturesFromCallables(signatures), + "")); + } + } + return Optional.empty(); + } + + private List resolveCallableSignatures( + final String callableName, + final ScopeState scopeState) { + final TopDeclSymbol importedSymbol = importedSymbols.get(callableName); + if (importedSymbol != null) { + return signaturesForTopDecl(importedSymbol.decl()); + } + final TopDeclSymbol topLevelSymbol = topLevelSymbols.get(callableName); + if (topLevelSymbol != null) { + return signaturesForTopDecl(topLevelSymbol.decl()); + } + final TopDeclSymbol supplementalSymbol = supplementalSymbols.get(callableName); + if (supplementalSymbol != null) { + return signaturesForTopDecl(supplementalSymbol.decl()); + } + return signaturesFromCallables(model.topLevelCallables.getOrDefault(callableName, List.of())); + } + + private List resolveMemberSignatures( + final TypeView receiverType, + final String memberName) { + return resolveMemberHover(receiverType, memberName) + .map(PbsEditorialResolvedSymbol::signatures) + .orElse(List.of()); + } + + private List resolveConstructorSignatures(final String typeName) { + final TopDeclSymbol importedSymbol = importedSymbols.get(typeName); + if (importedSymbol != null) { + return constructorSignaturesForTopDecl(importedSymbol.decl()); + } + final TopDeclSymbol topLevelSymbol = topLevelSymbols.get(typeName); + if (topLevelSymbol != null) { + return constructorSignaturesForTopDecl(topLevelSymbol.decl()); + } + final TopDeclSymbol supplementalSymbol = supplementalSymbols.get(typeName); + if (supplementalSymbol != null) { + return constructorSignaturesForTopDecl(supplementalSymbol.decl()); + } + return List.of(); + } + + private PbsEditorialResolvedSymbol symbolFromTopDecl( + final TopDeclSymbol topDeclSymbol, + final List signatures) { + final PbsEditorialSymbolKind kind = symbolKind(topDeclSymbol.decl()); + final String detail = signatures.isEmpty() + ? kind.name().toLowerCase(Locale.ROOT).replace('_', ' ') + : signatures.getFirst().label(); + return new PbsEditorialResolvedSymbol( + topDeclSymbol.localName(), + kind, + detail, + topDeclSymbol.origin(), + signatures, + ""); + } + + private PbsEditorialResolvedSymbol constructorSymbolFromTopDecl( + final TopDeclSymbol topDeclSymbol, + final List signatures) { + final String detail = signatures.isEmpty() + ? "constructor" + : signatures.getFirst().label(); + return new PbsEditorialResolvedSymbol( + topDeclSymbol.localName(), + PbsEditorialSymbolKind.CONSTRUCTOR, + detail, + topDeclSymbol.origin(), + signatures, + ""); + } + + private PbsEditorialCompletionCandidate completionFromTopDecl(final TopDeclSymbol topDeclSymbol) { + final List signatures = signaturesForTopDecl(topDeclSymbol.decl()); + final String detail = signatures.isEmpty() + ? symbolKind(topDeclSymbol.decl()).name().toLowerCase(Locale.ROOT).replace('_', ' ') + : signatures.getFirst().label(); + return new PbsEditorialCompletionCandidate( + topDeclSymbol.localName(), + symbolKind(topDeclSymbol.decl()), + detail, + topDeclSymbol.origin()); + } + + private List signaturesForTopDecl(final PbsAst.TopDecl topDecl) { + if (topDecl instanceof PbsAst.FunctionDecl functionDecl) { + return List.of(signatureFromFunction(functionDecl.name(), functionDecl.parameters(), functionDecl.returnKind(), functionDecl.returnType(), functionDecl.resultErrorType())); + } + if (topDecl instanceof PbsAst.CallbackDecl callbackDecl) { + return List.of(signatureFromFunction(callbackDecl.name(), callbackDecl.parameters(), callbackDecl.returnKind(), callbackDecl.returnType(), callbackDecl.resultErrorType())); + } + if (topDecl instanceof PbsAst.ServiceDecl serviceDecl) { + return serviceDecl.methods().stream() + .map(method -> signatureFromFunction(method.name(), method.parameters(), method.returnKind(), method.returnType(), method.resultErrorType())) + .toList(); + } + if (topDecl instanceof PbsAst.HostDecl hostDecl) { + return hostDecl.signatures().stream() + .map(signature -> signatureFromFunction(signature.name(), signature.parameters(), signature.returnKind(), signature.returnType(), signature.resultErrorType())) + .toList(); + } + if (topDecl instanceof PbsAst.ContractDecl contractDecl) { + return contractDecl.signatures().stream() + .map(signature -> signatureFromFunction(signature.name(), signature.parameters(), signature.returnKind(), signature.returnType(), signature.resultErrorType())) + .toList(); + } + if (topDecl instanceof PbsAst.BuiltinTypeDecl builtinTypeDecl) { + return builtinTypeDecl.signatures().stream() + .map(signature -> signatureFromFunction(signature.name(), signature.parameters(), signature.returnKind(), signature.returnType(), signature.resultErrorType())) + .toList(); + } + return List.of(); + } + + private List constructorSignaturesForTopDecl(final PbsAst.TopDecl topDecl) { + if (topDecl instanceof PbsAst.StructDecl structDecl) { + if (structDecl.ctors().isEmpty()) { + return List.of(new PbsEditorialSignature(structDecl.name(), structDecl.name() + "()", List.of(), "unit")); + } + return structDecl.ctors().stream() + .map(ctor -> signatureFromCtor(structDecl.name(), ctor)) + .toList(); + } + return List.of(); + } + + private List signaturesFromCallables(final List callables) { + if (callables == null || callables.isEmpty()) { + return List.of(); + } + final ArrayList signatures = new ArrayList<>(callables.size()); + for (final var callable : callables) { + final ArrayList parameterLabels = new ArrayList<>(callable.inputTypes().size()); + for (int index = 0; index < callable.inputTypes().size(); index += 1) { + parameterLabels.add("arg" + index + ": " + formatType(callable.inputTypes().get(index))); + } + final String label = callable.name() + "(" + String.join(", ", parameterLabels) + ") -> " + formatType(callable.outputType()); + signatures.add(new PbsEditorialSignature(callable.name(), label, parameterLabels, formatType(callable.outputType()))); + } + return List.copyOf(signatures); + } + + private PbsEditorialSignature signatureFromFunction( + final String callableName, + final ReadOnlyList parameters, + final PbsAst.ReturnKind returnKind, + final PbsAst.TypeRef returnType, + final PbsAst.TypeRef resultErrorType) { + final ArrayList parameterLabels = new ArrayList<>(parameters.size()); + for (final var parameter : parameters) { + parameterLabels.add(parameter.name() + ": " + formatTypeRef(aliasExpandedTypeRef(parameter.typeRef()))); + } + final String returnLabel = formatReturnType(returnKind, aliasExpandedTypeRef(returnType), aliasExpandedTypeRef(resultErrorType)); + return new PbsEditorialSignature( + callableName, + callableName + "(" + String.join(", ", parameterLabels) + ") -> " + returnLabel, + parameterLabels, + returnLabel); + } + + private PbsEditorialSignature signatureFromCtor( + final String ownerTypeName, + final PbsAst.CtorDecl ctorDecl) { + final ArrayList parameterLabels = new ArrayList<>(ctorDecl.parameters().size()); + for (final var parameter : ctorDecl.parameters()) { + parameterLabels.add(parameter.name() + ": " + formatTypeRef(aliasExpandedTypeRef(parameter.typeRef()))); + } + return new PbsEditorialSignature( + ownerTypeName, + ownerTypeName + "(" + String.join(", ", parameterLabels) + ")", + parameterLabels, + "unit"); + } + + private String formatCallableDetails(final List callables) { + if (callables == null || callables.isEmpty()) { + return ""; + } + return signaturesFromCallables(callables).getFirst().label(); + } + + private String formatType(final TypeView type) { + final String formatted = typeFormatter.format(type); + return formatted == null ? "unknown" : formatted; + } + + private String formatTypeRef(final PbsAst.TypeRef typeRef) { + if (typeRef == null) { + return "unit"; + } + return switch (typeRef.kind()) { + case UNIT -> "unit"; + case SELF -> "Self"; + case SIMPLE -> typeRef.name(); + case OPTIONAL -> formatTypeRef(typeRef.inner()) + "?"; + case GROUP -> formatTypeRef(typeRef.inner()); + case NAMED_TUPLE -> { + final ArrayList fields = new ArrayList<>(typeRef.fields().size()); + for (final var field : typeRef.fields()) { + fields.add(field.label() + ": " + formatTypeRef(field.typeRef())); + } + yield "(" + String.join(", ", fields) + ")"; + } + case ERROR -> "unknown"; + }; + } + + private String formatReturnType( + final PbsAst.ReturnKind returnKind, + final PbsAst.TypeRef returnType, + final PbsAst.TypeRef resultErrorType) { + return switch (returnKind) { + case INFERRED_UNIT, EXPLICIT_UNIT -> "unit"; + case PLAIN -> formatTypeRef(returnType); + case RESULT -> "result<" + formatTypeRef(resultErrorType) + ", " + formatTypeRef(returnType) + ">"; + }; + } + + private TypeView resolveReceiverTypeBeforeDot( + final int dotTokenIndex, + final ScopeState scopeState) { + final List segments = resolveChainSegmentsEndingAt(dotTokenIndex - 1); + if (segments.isEmpty()) { + return TypeView.unknown(); + } + TypeView current = resolveBaseChainType(segments.getFirst(), scopeState); + for (int index = 1; index < segments.size(); index += 1) { + current = resolveChainMemberType(current, segments.get(index)); + } + return current; + } + + private TypeView resolveBaseChainType( + final String baseName, + final ScopeState scopeState) { + if ("this".equals(baseName)) { + return scopeState.receiverType() == null ? TypeView.unknown() : scopeState.receiverType(); + } + final TypeView localType = scopeState.scope().resolve(baseName); + if (localType != null) { + return localType; + } + final TopDeclSymbol importedSymbol = importedSymbols.get(baseName); + if (importedSymbol != null) { + return typeForTopDecl(importedSymbol.decl()); + } + final TopDeclSymbol topLevelSymbol = topLevelSymbols.get(baseName); + if (topLevelSymbol != null) { + return typeForTopDecl(topLevelSymbol.decl()); + } + final TopDeclSymbol supplementalSymbol = supplementalSymbols.get(baseName); + if (supplementalSymbol != null) { + return typeForTopDecl(supplementalSymbol.decl()); + } + if ("assets".equals(baseName)) { + return TypeView.assetNamespace("assets"); + } + return TypeView.unknown(); + } + + private TypeView resolveChainMemberType( + final TypeView receiverType, + final String memberName) { + if (receiverType.kind() == Kind.STRUCT) { + final StructInfo structInfo = model.structs.get(receiverType.name()); + if (structInfo == null) { + return TypeView.unknown(); + } + final StructFieldInfo field = structInfo.fields().get(memberName); + return field == null ? TypeView.unknown() : field.type(); + } + if (receiverType.kind() == Kind.ASSET_NAMESPACE) { + final String candidate = receiverType.name() + "." + memberName; + if (model.resolveAssetId(candidate) != null) { + return TypeView.addressable(candidate); + } + if (model.isAssetNamespace(candidate)) { + return TypeView.assetNamespace(candidate); + } + } + return TypeView.unknown(); + } + + private TypeView typeForTopDecl(final PbsAst.TopDecl topDecl) { + if (topDecl instanceof PbsAst.StructDecl structDecl) { + return TypeView.struct(structDecl.name()); + } + if (topDecl instanceof PbsAst.BuiltinTypeDecl builtinTypeDecl) { + return TypeView.struct(builtinTypeDecl.name()); + } + if (topDecl instanceof PbsAst.ServiceDecl serviceDecl) { + return TypeView.service(serviceDecl.name()); + } + if (topDecl instanceof PbsAst.HostDecl hostDecl) { + return TypeView.service(hostDecl.name()); + } + if (topDecl instanceof PbsAst.ContractDecl contractDecl) { + return TypeView.contract(contractDecl.name()); + } + if (topDecl instanceof PbsAst.EnumDecl enumDecl) { + return TypeView.enumType(enumDecl.name()); + } + if (topDecl instanceof PbsAst.ErrorDecl errorDecl) { + return TypeView.error(errorDecl.name()); + } + if (topDecl instanceof PbsAst.CallbackDecl callbackDecl) { + return typeOps.typeFromTypeRef(PbsAst.TypeRef.simple(callbackDecl.name(), callbackDecl.span()), model, null); + } + return TypeView.unknown(); + } + + private CallSite callSiteAt(final int offset) { + int depth = 0; + int activeParameter = 0; + for (int index = significantTokenCount() - 1; index >= 0; index -= 1) { + final PbsToken token = significantToken(index); + if (token.start() >= offset) { + continue; + } + if (token.kind() == PbsTokenKind.RIGHT_PAREN) { + depth += 1; + continue; + } + if (token.kind() == PbsTokenKind.LEFT_PAREN) { + if (depth == 0) { + final Integer calleeIndex = previousSignificantTokenIndex(tokenIndex(token)); + if (calleeIndex == null) { + return null; + } + final PbsToken calleeToken = token(calleeIndex); + if (calleeToken.kind() != PbsTokenKind.IDENTIFIER) { + return null; + } + final Integer maybeDotIndex = previousSignificantTokenIndex(calleeIndex); + if (maybeDotIndex != null && token(maybeDotIndex).kind() == PbsTokenKind.DOT) { + return new CallSite(CallSiteKind.MEMBER, calleeToken.lexeme(), activeParameter, maybeDotIndex); + } + if (maybeDotIndex != null && token(maybeDotIndex).kind() == PbsTokenKind.NEW) { + return new CallSite(CallSiteKind.CONSTRUCTOR, calleeToken.lexeme(), activeParameter, -1); + } + return new CallSite(CallSiteKind.FUNCTION, calleeToken.lexeme(), activeParameter, -1); + } + depth -= 1; + continue; + } + if (depth == 0 && token.kind() == PbsTokenKind.COMMA) { + activeParameter += 1; + } + } + return null; + } + + private Integer identifierTokenIndexAt(final int offset) { + for (int index = 0; index < tokens.size(); index += 1) { + final PbsToken token = tokens.get(index); + if (token.kind() == PbsTokenKind.IDENTIFIER && token.start() <= offset && token.end() > offset) { + return index; + } + } + return null; + } + + private Integer previousSignificantTokenIndexAt(final int offset) { + for (int index = tokens.size() - 1; index >= 0; index -= 1) { + final PbsToken token = tokens.get(index); + if (token.kind() == PbsTokenKind.COMMENT || token.kind() == PbsTokenKind.EOF) { + continue; + } + if (token.end() <= offset) { + return index; + } + } + return null; + } + + private Integer previousSignificantTokenIndex(final int index) { + for (int cursor = index - 1; cursor >= 0; cursor -= 1) { + final PbsToken token = tokens.get(cursor); + if (token.kind() == PbsTokenKind.COMMENT || token.kind() == PbsTokenKind.EOF) { + continue; + } + return cursor; + } + return null; + } + + private List resolveChainSegmentsEndingAt(final int endTokenIndex) { + final ArrayList reversedSegments = new ArrayList<>(); + int cursor = endTokenIndex; + boolean expectIdentifier = true; + while (cursor >= 0) { + final PbsToken token = tokens.get(cursor); + if (token.kind() == PbsTokenKind.COMMENT || token.kind() == PbsTokenKind.EOF) { + cursor -= 1; + continue; + } + if (expectIdentifier) { + if (token.kind() == PbsTokenKind.IDENTIFIER) { + reversedSegments.add(token.lexeme()); + expectIdentifier = false; + cursor -= 1; + continue; + } + if (token.kind() == PbsTokenKind.THIS) { + reversedSegments.add("this"); + } + break; + } + if (token.kind() != PbsTokenKind.DOT) { + break; + } + expectIdentifier = true; + cursor -= 1; + } + Collections.reverse(reversedSegments); + return List.copyOf(reversedSegments); + } + + private int tokenIndex(final PbsToken needle) { + for (int index = 0; index < tokens.size(); index += 1) { + if (tokens.get(index) == needle) { + return index; + } + } + return -1; + } + + private int significantTokenCount() { + int count = 0; + for (final var token : tokens) { + if (token.kind() != PbsTokenKind.COMMENT && token.kind() != PbsTokenKind.EOF) { + count += 1; + } + } + return count; + } + + private PbsToken significantToken(final int significantIndex) { + int cursor = 0; + for (final var token : tokens) { + if (token.kind() == PbsTokenKind.COMMENT || token.kind() == PbsTokenKind.EOF) { + continue; + } + if (cursor == significantIndex) { + return token; + } + cursor += 1; + } + throw new IndexOutOfBoundsException("No significant token at index " + significantIndex); + } + + private PbsToken token(final int index) { + return tokens.get(index); + } + + private PbsAst.TypeRef aliasExpandedTypeRef(final PbsAst.TypeRef typeRef) { + if (typeRef == null) { + return null; + } + return switch (typeRef.kind()) { + case SIMPLE -> aliasedTypeRefs.getOrDefault(typeRef.name(), typeRef); + case OPTIONAL -> PbsAst.TypeRef.optional(aliasExpandedTypeRef(typeRef.inner()), typeRef.span()); + case GROUP -> PbsAst.TypeRef.group(aliasExpandedTypeRef(typeRef.inner()), typeRef.span()); + case NAMED_TUPLE -> { + final ArrayList fields = new ArrayList<>(typeRef.fields().size()); + for (final var field : typeRef.fields()) { + fields.add(new PbsAst.NamedTypeField(field.label(), aliasExpandedTypeRef(field.typeRef()), field.span())); + } + yield new PbsAst.TypeRef(PbsAst.TypeRefKind.NAMED_TUPLE, typeRef.name(), ReadOnlyList.wrap(fields), null, typeRef.span()); + } + case UNIT, SELF, ERROR -> typeRef; + }; + } + + private PbsAst.TopDecl findSupplementalTopDecl( + final String name, + final List supplementals) { + for (final var topDecl : supplementals) { + if (name.equals(topDeclName(topDecl))) { + return topDecl; + } + } + return null; + } + + private String topDeclName(final PbsAst.TopDecl topDecl) { + if (topDecl instanceof PbsAst.FunctionDecl functionDecl) { + return functionDecl.name(); + } + if (topDecl instanceof PbsAst.StructDecl structDecl) { + return structDecl.name(); + } + if (topDecl instanceof PbsAst.BuiltinTypeDecl builtinTypeDecl) { + return builtinTypeDecl.name(); + } + if (topDecl instanceof PbsAst.ServiceDecl serviceDecl) { + return serviceDecl.name(); + } + if (topDecl instanceof PbsAst.HostDecl hostDecl) { + return hostDecl.name(); + } + if (topDecl instanceof PbsAst.ContractDecl contractDecl) { + return contractDecl.name(); + } + if (topDecl instanceof PbsAst.CallbackDecl callbackDecl) { + return callbackDecl.name(); + } + if (topDecl instanceof PbsAst.EnumDecl enumDecl) { + return enumDecl.name(); + } + if (topDecl instanceof PbsAst.ErrorDecl errorDecl) { + return errorDecl.name(); + } + if (topDecl instanceof PbsAst.GlobalDecl globalDecl) { + return globalDecl.name(); + } + if (topDecl instanceof PbsAst.ConstDecl constDecl) { + return constDecl.name(); + } + return null; + } + + private String formatModuleRef(final PbsAst.ModuleRef moduleRef) { + if (moduleRef == null) { + return ""; + } + if (moduleRef.pathSegments().isEmpty()) { + return "@%s:".formatted(moduleRef.project()); + } + return "@%s:%s".formatted(moduleRef.project(), String.join("/", moduleRef.pathSegments().asList())); + } + + private PbsAst.TopDecl cloneTopDeclWithName( + final PbsAst.TopDecl topDecl, + final String newName) { + if (topDecl instanceof PbsAst.FunctionDecl functionDecl) { + return new PbsAst.FunctionDecl( + newName, + functionDecl.parameters(), + functionDecl.returnKind(), + functionDecl.returnType(), + functionDecl.resultErrorType(), + functionDecl.lifecycleMarker(), + functionDecl.body(), + functionDecl.span()); + } + if (topDecl instanceof PbsAst.StructDecl structDecl) { + return new PbsAst.StructDecl( + newName, + structDecl.fields(), + structDecl.methods(), + structDecl.ctors(), + structDecl.hasBody(), + structDecl.span()); + } + if (topDecl instanceof PbsAst.BuiltinTypeDecl builtinTypeDecl) { + return new PbsAst.BuiltinTypeDecl( + newName, + builtinTypeDecl.fields(), + builtinTypeDecl.signatures(), + builtinTypeDecl.attributes(), + builtinTypeDecl.span()); + } + if (topDecl instanceof PbsAst.ServiceDecl serviceDecl) { + return new PbsAst.ServiceDecl(newName, serviceDecl.methods(), serviceDecl.span()); + } + if (topDecl instanceof PbsAst.HostDecl hostDecl) { + return new PbsAst.HostDecl(newName, hostDecl.signatures(), hostDecl.span()); + } + if (topDecl instanceof PbsAst.ContractDecl contractDecl) { + return new PbsAst.ContractDecl(newName, contractDecl.signatures(), contractDecl.span()); + } + if (topDecl instanceof PbsAst.CallbackDecl callbackDecl) { + return new PbsAst.CallbackDecl( + newName, + callbackDecl.parameters(), + callbackDecl.returnKind(), + callbackDecl.returnType(), + callbackDecl.resultErrorType(), + callbackDecl.span()); + } + if (topDecl instanceof PbsAst.EnumDecl enumDecl) { + return new PbsAst.EnumDecl(newName, enumDecl.cases(), enumDecl.span()); + } + if (topDecl instanceof PbsAst.ErrorDecl errorDecl) { + return new PbsAst.ErrorDecl(newName, errorDecl.cases(), errorDecl.span()); + } + if (topDecl instanceof PbsAst.GlobalDecl globalDecl) { + return new PbsAst.GlobalDecl(newName, globalDecl.explicitType(), globalDecl.initializer(), globalDecl.span()); + } + if (topDecl instanceof PbsAst.ConstDecl constDecl) { + return new PbsAst.ConstDecl(newName, constDecl.explicitType(), constDecl.initializer(), constDecl.attributes(), constDecl.span()); + } + return topDecl; + } + + private TopDeclSymbol resolveTopDeclSymbol(final String symbolName) { + final TopDeclSymbol importedSymbol = importedSymbols.get(symbolName); + if (importedSymbol != null) { + return importedSymbol; + } + final TopDeclSymbol topLevelSymbol = topLevelSymbols.get(symbolName); + if (topLevelSymbol != null) { + return topLevelSymbol; + } + return supplementalSymbols.get(symbolName); + } + + private PbsEditorialSymbolKind symbolKind(final PbsAst.TopDecl topDecl) { + if (topDecl instanceof PbsAst.FunctionDecl) { + return PbsEditorialSymbolKind.FUNCTION; + } + if (topDecl instanceof PbsAst.StructDecl) { + return PbsEditorialSymbolKind.STRUCT; + } + if (topDecl instanceof PbsAst.BuiltinTypeDecl) { + return PbsEditorialSymbolKind.BUILTIN_TYPE; + } + if (topDecl instanceof PbsAst.ServiceDecl) { + return PbsEditorialSymbolKind.SERVICE; + } + if (topDecl instanceof PbsAst.HostDecl) { + return PbsEditorialSymbolKind.HOST; + } + if (topDecl instanceof PbsAst.ContractDecl) { + return PbsEditorialSymbolKind.CONTRACT; + } + if (topDecl instanceof PbsAst.CallbackDecl) { + return PbsEditorialSymbolKind.CALLBACK; + } + if (topDecl instanceof PbsAst.EnumDecl) { + return PbsEditorialSymbolKind.ENUM; + } + if (topDecl instanceof PbsAst.ErrorDecl) { + return PbsEditorialSymbolKind.ERROR; + } + if (topDecl instanceof PbsAst.GlobalDecl) { + return PbsEditorialSymbolKind.GLOBAL; + } + if (topDecl instanceof PbsAst.ConstDecl) { + return PbsEditorialSymbolKind.CONST; + } + throw new IllegalArgumentException("Unsupported top declaration: " + topDecl.getClass().getSimpleName()); + } + + private String errorName(final PbsAst.TypeRef typeRef) { + return typeRef == null ? null : typeRef.name(); + } + } + + private record TopDeclSymbol( + String localName, + PbsAst.TopDecl decl, + String origin) { + } + + private record CallableFrame( + ReadOnlyList parameters, + PbsAst.Block body, + TypeView receiverType, + TypeView returnType, + String resultErrorName) { + private Set parameterNames() { + final Set names = new LinkedHashSet<>(); + for (final var parameter : parameters) { + names.add(parameter.name()); + } + return Set.copyOf(names); + } + } + + private record ScopeState( + Scope scope, + TypeView receiverType, + TypeView returnType, + String resultErrorName, + Set parameterNames) { + } + + private enum CallSiteKind { + FUNCTION, + MEMBER, + CONSTRUCTOR + } + + private record CallSite( + CallSiteKind kind, + String name, + int activeParameter, + int memberDotTokenIndex) { + } +} diff --git a/prometeu-compiler/frontends/prometeu-frontend-pbs/src/main/java/p/studio/compiler/pbs/semantics/PbsEditorialSymbolKind.java b/prometeu-compiler/frontends/prometeu-frontend-pbs/src/main/java/p/studio/compiler/pbs/semantics/PbsEditorialSymbolKind.java new file mode 100644 index 00000000..f684dd38 --- /dev/null +++ b/prometeu-compiler/frontends/prometeu-frontend-pbs/src/main/java/p/studio/compiler/pbs/semantics/PbsEditorialSymbolKind.java @@ -0,0 +1,21 @@ +package p.studio.compiler.pbs.semantics; + +public enum PbsEditorialSymbolKind { + KEYWORD, + LOCAL, + PARAMETER, + FIELD, + FUNCTION, + METHOD, + CONSTRUCTOR, + STRUCT, + BUILTIN_TYPE, + SERVICE, + HOST, + CONTRACT, + CALLBACK, + ENUM, + ERROR, + GLOBAL, + CONST +} diff --git a/prometeu-compiler/frontends/prometeu-frontend-pbs/src/main/java/p/studio/compiler/pbs/semantics/PbsFlowSemanticSupport.java b/prometeu-compiler/frontends/prometeu-frontend-pbs/src/main/java/p/studio/compiler/pbs/semantics/PbsFlowSemanticSupport.java index ee33549a..70aeefae 100644 --- a/prometeu-compiler/frontends/prometeu-frontend-pbs/src/main/java/p/studio/compiler/pbs/semantics/PbsFlowSemanticSupport.java +++ b/prometeu-compiler/frontends/prometeu-frontend-pbs/src/main/java/p/studio/compiler/pbs/semantics/PbsFlowSemanticSupport.java @@ -584,5 +584,9 @@ final class PbsFlowSemanticSupport { final var symbol = names.get(name); return symbol != null && symbol.mutable(); } + + Map entries() { + return Map.copyOf(names); + } } } diff --git a/prometeu-compiler/frontends/prometeu-frontend-pbs/src/main/java/p/studio/compiler/services/PBSFrontendPhaseService.java b/prometeu-compiler/frontends/prometeu-frontend-pbs/src/main/java/p/studio/compiler/services/PBSFrontendPhaseService.java index 27341fff..6aaa8bc7 100644 --- a/prometeu-compiler/frontends/prometeu-frontend-pbs/src/main/java/p/studio/compiler/services/PBSFrontendPhaseService.java +++ b/prometeu-compiler/frontends/prometeu-frontend-pbs/src/main/java/p/studio/compiler/services/PBSFrontendPhaseService.java @@ -133,12 +133,14 @@ public class PBSFrontendPhaseService implements FrontendPhaseService { assembly.parsedSourceFiles(), assembly.moduleTable()); final var flowSemanticsValidator = new PbsFlowSemanticsValidator(); + final Map astByFile = new LinkedHashMap<>(); final Map> supplementalTopDeclsByFile = new LinkedHashMap<>(); final Map> inlineHintsByFile = new LinkedHashMap<>(); for (final var entry : importedSemanticContexts.entrySet()) { supplementalTopDeclsByFile.put(entry.getKey(), entry.getValue().supplementalTopDecls()); } for (final var parsedSourceFile : assembly.parsedSourceFiles()) { + astByFile.put(parsedSourceFile.fileId(), parsedSourceFile.ast()); final var importedSemanticContext = importedSemanticContexts.getOrDefault( parsedSourceFile.fileId(), PbsImportedSemanticContext.empty()); @@ -152,11 +154,13 @@ public class PBSFrontendPhaseService implements FrontendPhaseService { } } return new PbsSemanticReadSurface( + Map.copyOf(astByFile), Map.copyOf(supplementalTopDeclsByFile), Map.copyOf(inlineHintsByFile)); } public record PbsSemanticReadSurface( + Map astByFile, Map> supplementalTopDeclsByFile, Map> inlineHintsByFile) { } diff --git a/prometeu-compiler/frontends/prometeu-frontend-pbs/src/test/java/p/studio/compiler/pbs/semantics/PbsEditorialSupportServiceTest.java b/prometeu-compiler/frontends/prometeu-frontend-pbs/src/test/java/p/studio/compiler/pbs/semantics/PbsEditorialSupportServiceTest.java new file mode 100644 index 00000000..b9458adb --- /dev/null +++ b/prometeu-compiler/frontends/prometeu-frontend-pbs/src/test/java/p/studio/compiler/pbs/semantics/PbsEditorialSupportServiceTest.java @@ -0,0 +1,215 @@ +package p.studio.compiler.pbs.semantics; + +import org.junit.jupiter.api.Test; +import p.studio.compiler.pbs.ast.PbsAst; +import p.studio.compiler.pbs.lexer.PbsLexer; +import p.studio.compiler.pbs.parser.PbsParser; +import p.studio.compiler.source.diagnostics.DiagnosticSink; +import p.studio.compiler.source.identifiers.FileId; +import p.studio.utilities.structures.ReadOnlyList; + +import java.util.ArrayList; +import java.util.List; + +import static org.junit.jupiter.api.Assertions.*; + +final class PbsEditorialSupportServiceTest { + private final PbsEditorialSupportService service = new PbsEditorialSupportService(); + + @Test + void shouldResolveGeneralCompletionAndHoverAcrossLocalAndImportedSymbols() { + final var source = """ + import { Log } from @sdk:log; + + fn helper(value: int) -> int { + let total = value; + Log.info("hello"); + return total; + } + """; + final var ast = parseOrdinary(source); + final var supplementalTopDecls = supplementalTopDecls(""" + declare service Log { + fn info(message: str) -> void { + return; + } + } + """); + + final var completions = service.completion( + source, + ast, + supplementalTopDecls, + source.indexOf("return total")); + + assertTrue(completions.stream().anyMatch(candidate -> + candidate.label().equals("fn") && candidate.kind() == PbsEditorialSymbolKind.KEYWORD)); + assertTrue(completions.stream().anyMatch(candidate -> + candidate.label().equals("value") && candidate.kind() == PbsEditorialSymbolKind.PARAMETER)); + assertTrue(completions.stream().anyMatch(candidate -> + candidate.label().equals("total") && candidate.kind() == PbsEditorialSymbolKind.LOCAL)); + assertTrue(completions.stream().anyMatch(candidate -> + candidate.label().equals("Log") && candidate.kind() == PbsEditorialSymbolKind.SERVICE)); + assertTrue(completions.stream().anyMatch(candidate -> + candidate.label().equals("helper") && candidate.kind() == PbsEditorialSymbolKind.FUNCTION)); + + final var parameterHover = requireHover(source, ast, supplementalTopDecls, "value;"); + assertEquals(PbsEditorialSymbolKind.PARAMETER, parameterHover.kind()); + assertEquals("int", parameterHover.detail()); + + final var importedHover = requireHover(source, ast, supplementalTopDecls, "Log.info"); + assertEquals(PbsEditorialSymbolKind.SERVICE, importedHover.kind()); + assertEquals("@sdk:log", importedHover.origin()); + } + + @Test + void shouldResolveMemberCompletionAndHoverForImportedHostAndBuiltinTypes() { + final var source = """ + import { Input } from @sdk:input; + + fn main() -> void { + let touch: InputTouch = Input.touch(); + Input.touch(); + touch.x_axis(); + } + """; + final var ast = parseOrdinary(source); + final var supplementalTopDecls = supplementalTopDecls(""" + declare builtin type InputTouch( + pub x: int + ) { + fn x_axis() -> int; + } + + declare host Input { + fn touch() -> InputTouch; + fn pad() -> InputPad; + } + + declare builtin type InputPad( + pub id: int + ) { + fn strength() -> int; + } + """); + + final var hostMembers = service.completion( + source, + ast, + supplementalTopDecls, + source.indexOf("touch();")); + + assertTrue(hostMembers.stream().anyMatch(candidate -> + candidate.label().equals("touch") && candidate.kind() == PbsEditorialSymbolKind.METHOD)); + assertTrue(hostMembers.stream().anyMatch(candidate -> + candidate.label().equals("pad") && candidate.kind() == PbsEditorialSymbolKind.METHOD)); + + final var builtinMembers = service.completion( + source, + ast, + supplementalTopDecls, + source.indexOf("x_axis();")); + + assertTrue(builtinMembers.stream().anyMatch(candidate -> + candidate.label().equals("x") && candidate.kind() == PbsEditorialSymbolKind.FIELD)); + assertTrue(builtinMembers.stream().anyMatch(candidate -> + candidate.label().equals("x_axis") && candidate.kind() == PbsEditorialSymbolKind.METHOD)); + + final var builtinTypeHover = requireHover(source, ast, supplementalTopDecls, "InputTouch"); + assertEquals(PbsEditorialSymbolKind.BUILTIN_TYPE, builtinTypeHover.kind()); + + final var hostMethodHover = requireHover(source, ast, supplementalTopDecls, "touch();"); + assertEquals(PbsEditorialSymbolKind.METHOD, hostMethodHover.kind()); + assertEquals("Input", hostMethodHover.origin()); + } + + @Test + void shouldResolveSignatureHelpForFunctionMethodAndConstructorCalls() { + final var source = """ + declare struct Vec() { + fn blend(dx: int, dy: int) -> int { return dx; } + } + + fn mix(left: int, right: int) -> int { return left; } + + fn main(vec: Vec) -> void { + mix(1, 2); + vec.blend(1, 2); + new Vec(); + } + """; + final var ast = parseOrdinary(source); + + final var functionHelp = service.signatureHelp( + source, + ast, + ReadOnlyList.empty(), + source.indexOf("2);")); + assertTrue(functionHelp.isPresent()); + assertEquals("mix(left: int, right: int) -> int", functionHelp.orElseThrow().signatures().getFirst().label()); + assertEquals(1, functionHelp.orElseThrow().activeParameter()); + + final var methodHelp = service.signatureHelp( + source, + ast, + ReadOnlyList.empty(), + source.lastIndexOf("2);")); + assertTrue(methodHelp.isPresent()); + assertEquals("blend(arg0: int, arg1: int) -> int", methodHelp.orElseThrow().signatures().getFirst().label()); + assertEquals(1, methodHelp.orElseThrow().activeParameter()); + + final var constructorHelp = service.signatureHelp( + source, + ast, + ReadOnlyList.empty(), + source.indexOf("Vec();") + 4); + assertTrue(constructorHelp.isPresent()); + assertEquals("Vec()", constructorHelp.orElseThrow().signatures().getFirst().label()); + + final var constructorHover = requireHover(source, ast, ReadOnlyList.empty(), "Vec();"); + assertEquals(PbsEditorialSymbolKind.CONSTRUCTOR, constructorHover.kind()); + assertEquals("Vec()", constructorHover.signatures().getFirst().label()); + } + + private PbsEditorialResolvedSymbol requireHover( + final String source, + final PbsAst.File ast, + final ReadOnlyList supplementalTopDecls, + final String needle) { + final int offset = source.indexOf(needle); + assertTrue(offset >= 0, "Expected to find needle: " + needle); + return service.hover(source, ast, supplementalTopDecls, offset) + .orElseThrow(); + } + + private ReadOnlyList supplementalTopDecls(final String... interfaceModuleSources) { + final ArrayList topDecls = new ArrayList<>(); + int fileNumber = 100; + for (final var source : interfaceModuleSources) { + topDecls.addAll(parseInterface(source, new FileId(fileNumber)).topDecls().asList()); + fileNumber += 1; + } + return ReadOnlyList.wrap(topDecls); + } + + private PbsAst.File parseOrdinary(final String source) { + return parse(source, new FileId(0), PbsParser.ParseMode.ORDINARY); + } + + private PbsAst.File parseInterface( + final String source, + final FileId fileId) { + return parse(source, fileId, PbsParser.ParseMode.INTERFACE_MODULE); + } + + private PbsAst.File parse( + final String source, + final FileId fileId, + final PbsParser.ParseMode parseMode) { + final var diagnostics = DiagnosticSink.empty(); + final var tokens = PbsLexer.lex(source, fileId, diagnostics); + final var ast = PbsParser.parse(tokens, fileId, diagnostics, parseMode); + assertFalse(diagnostics.hasErrors(), () -> "Unexpected parse errors: " + diagnostics.stream().toList()); + return ast; + } +} -- 2.47.2 From 7cbe61f5eb3676c926d15a065cb60b7179780eb9 Mon Sep 17 00:00:00 2001 From: bQUARKz Date: Fri, 8 May 2026 10:13:38 +0100 Subject: [PATCH 35/37] implements PLN-0076 --- prometeu-lsp/prometeu-lsp-v1/build.gradle.kts | 3 + .../lsp/messages/BaselineCompletion.java | 12 + .../lsp/messages/BaselineCompletionItem.java | 30 +++ .../messages/BaselineCompletionItemKind.java | 20 ++ .../messages/BaselineServerDescription.java | 2 + .../lsp/messages/BaselineSignature.java | 29 +++ .../lsp/messages/BaselineSignatureHelp.java | 19 ++ .../lsp/services/LanguageServiceBridge.java | 8 +- .../CompilerLanguageServiceBridge.java | 225 +++++++++++++++++- .../compiler/DocumentPositionMapper.java | 36 ++- .../protocol/PrometeuTextDocumentService.java | 33 ++- .../mapping/Lsp4jProtocolMessageMapper.java | 77 ++++++ .../mapping/ProtocolMessageMapper.java | 8 + .../CompilerLanguageServiceBridgeTest.java | 67 ++++++ .../protocol/PrometeuLanguageServerTest.java | 45 +++- .../Lsp4jProtocolMessageMapperTest.java | 41 ++++ 16 files changed, 643 insertions(+), 12 deletions(-) create mode 100644 prometeu-lsp/prometeu-lsp-v1/src/main/java/p/studio/lsp/messages/BaselineCompletion.java create mode 100644 prometeu-lsp/prometeu-lsp-v1/src/main/java/p/studio/lsp/messages/BaselineCompletionItem.java create mode 100644 prometeu-lsp/prometeu-lsp-v1/src/main/java/p/studio/lsp/messages/BaselineCompletionItemKind.java create mode 100644 prometeu-lsp/prometeu-lsp-v1/src/main/java/p/studio/lsp/messages/BaselineSignature.java create mode 100644 prometeu-lsp/prometeu-lsp-v1/src/main/java/p/studio/lsp/messages/BaselineSignatureHelp.java diff --git a/prometeu-lsp/prometeu-lsp-v1/build.gradle.kts b/prometeu-lsp/prometeu-lsp-v1/build.gradle.kts index addf13e3..c2b12b6f 100644 --- a/prometeu-lsp/prometeu-lsp-v1/build.gradle.kts +++ b/prometeu-lsp/prometeu-lsp-v1/build.gradle.kts @@ -5,7 +5,10 @@ plugins { dependencies { implementation(project(":prometeu-lsp:prometeu-lsp-api")) implementation(project(":prometeu-compiler:prometeu-compiler-core")) + implementation(project(":prometeu-compiler:prometeu-frontend-api")) implementation(project(":prometeu-compiler:prometeu-build-pipeline")) + implementation(project(":prometeu-compiler:frontends:prometeu-frontend-pbs")) implementation(project(":prometeu-compiler:prometeu-frontend-registry")) + implementation(project(":prometeu-compiler:prometeu-deps")) implementation(libs.lsp4j) } diff --git a/prometeu-lsp/prometeu-lsp-v1/src/main/java/p/studio/lsp/messages/BaselineCompletion.java b/prometeu-lsp/prometeu-lsp-v1/src/main/java/p/studio/lsp/messages/BaselineCompletion.java new file mode 100644 index 00000000..335191cd --- /dev/null +++ b/prometeu-lsp/prometeu-lsp-v1/src/main/java/p/studio/lsp/messages/BaselineCompletion.java @@ -0,0 +1,12 @@ +package p.studio.lsp.messages; + +import java.util.List; +import java.util.Objects; + +public record BaselineCompletion( + boolean incomplete, + List items) { + public BaselineCompletion { + items = List.copyOf(Objects.requireNonNull(items, "items")); + } +} diff --git a/prometeu-lsp/prometeu-lsp-v1/src/main/java/p/studio/lsp/messages/BaselineCompletionItem.java b/prometeu-lsp/prometeu-lsp-v1/src/main/java/p/studio/lsp/messages/BaselineCompletionItem.java new file mode 100644 index 00000000..6dc80510 --- /dev/null +++ b/prometeu-lsp/prometeu-lsp-v1/src/main/java/p/studio/lsp/messages/BaselineCompletionItem.java @@ -0,0 +1,30 @@ +package p.studio.lsp.messages; + +import java.util.Objects; + +public record BaselineCompletionItem( + String label, + BaselineCompletionItemKind kind, + String detail, + String documentation) { + public BaselineCompletionItem { + label = requireText(label, "label"); + kind = Objects.requireNonNull(kind, "kind"); + detail = normalize(detail); + documentation = normalize(documentation); + } + + private static String requireText( + final String value, + final String field) { + final String candidate = normalize(value); + if (candidate.isEmpty()) { + throw new IllegalArgumentException(field + " must not be blank"); + } + return candidate; + } + + private static String normalize(final String value) { + return value == null ? "" : value.trim(); + } +} diff --git a/prometeu-lsp/prometeu-lsp-v1/src/main/java/p/studio/lsp/messages/BaselineCompletionItemKind.java b/prometeu-lsp/prometeu-lsp-v1/src/main/java/p/studio/lsp/messages/BaselineCompletionItemKind.java new file mode 100644 index 00000000..28da0724 --- /dev/null +++ b/prometeu-lsp/prometeu-lsp-v1/src/main/java/p/studio/lsp/messages/BaselineCompletionItemKind.java @@ -0,0 +1,20 @@ +package p.studio.lsp.messages; + +public enum BaselineCompletionItemKind { + KEYWORD, + VARIABLE, + FIELD, + FUNCTION, + METHOD, + CONSTRUCTOR, + STRUCT, + BUILTIN_TYPE, + SERVICE, + HOST, + CONTRACT, + CALLBACK, + ENUM, + ERROR, + GLOBAL, + CONST +} diff --git a/prometeu-lsp/prometeu-lsp-v1/src/main/java/p/studio/lsp/messages/BaselineServerDescription.java b/prometeu-lsp/prometeu-lsp-v1/src/main/java/p/studio/lsp/messages/BaselineServerDescription.java index 6af55458..96a5461c 100644 --- a/prometeu-lsp/prometeu-lsp-v1/src/main/java/p/studio/lsp/messages/BaselineServerDescription.java +++ b/prometeu-lsp/prometeu-lsp-v1/src/main/java/p/studio/lsp/messages/BaselineServerDescription.java @@ -8,6 +8,8 @@ public record BaselineServerDescription( String version, String frontendLanguageId, boolean hoverSupported, + boolean completionSupported, + boolean signatureHelpSupported, List semanticTokenTypes, List semanticHostProjections, List visualThemes, diff --git a/prometeu-lsp/prometeu-lsp-v1/src/main/java/p/studio/lsp/messages/BaselineSignature.java b/prometeu-lsp/prometeu-lsp-v1/src/main/java/p/studio/lsp/messages/BaselineSignature.java new file mode 100644 index 00000000..6ba774de --- /dev/null +++ b/prometeu-lsp/prometeu-lsp-v1/src/main/java/p/studio/lsp/messages/BaselineSignature.java @@ -0,0 +1,29 @@ +package p.studio.lsp.messages; + +import java.util.List; +import java.util.Objects; + +public record BaselineSignature( + String label, + List parameters, + String documentation) { + public BaselineSignature { + label = requireText(label, "label"); + parameters = List.copyOf(Objects.requireNonNull(parameters, "parameters")); + documentation = normalize(documentation); + } + + private static String requireText( + final String value, + final String field) { + final String candidate = normalize(value); + if (candidate.isEmpty()) { + throw new IllegalArgumentException(field + " must not be blank"); + } + return candidate; + } + + private static String normalize(final String value) { + return value == null ? "" : value.trim(); + } +} diff --git a/prometeu-lsp/prometeu-lsp-v1/src/main/java/p/studio/lsp/messages/BaselineSignatureHelp.java b/prometeu-lsp/prometeu-lsp-v1/src/main/java/p/studio/lsp/messages/BaselineSignatureHelp.java new file mode 100644 index 00000000..12bb6a4e --- /dev/null +++ b/prometeu-lsp/prometeu-lsp-v1/src/main/java/p/studio/lsp/messages/BaselineSignatureHelp.java @@ -0,0 +1,19 @@ +package p.studio.lsp.messages; + +import java.util.List; +import java.util.Objects; + +public record BaselineSignatureHelp( + List signatures, + int activeSignature, + int activeParameter) { + public BaselineSignatureHelp { + signatures = List.copyOf(Objects.requireNonNull(signatures, "signatures")); + if (!signatures.isEmpty() && (activeSignature < 0 || activeSignature >= signatures.size())) { + throw new IllegalArgumentException("activeSignature must reference one of the provided signatures"); + } + if (activeParameter < 0) { + throw new IllegalArgumentException("activeParameter must be >= 0"); + } + } +} diff --git a/prometeu-lsp/prometeu-lsp-v1/src/main/java/p/studio/lsp/services/LanguageServiceBridge.java b/prometeu-lsp/prometeu-lsp-v1/src/main/java/p/studio/lsp/services/LanguageServiceBridge.java index aa1ea97d..f7e7d543 100644 --- a/prometeu-lsp/prometeu-lsp-v1/src/main/java/p/studio/lsp/services/LanguageServiceBridge.java +++ b/prometeu-lsp/prometeu-lsp-v1/src/main/java/p/studio/lsp/services/LanguageServiceBridge.java @@ -1,8 +1,10 @@ package p.studio.lsp.services; import p.studio.lsp.messages.BaselineDocumentAnalysis; +import p.studio.lsp.messages.BaselineCompletion; import p.studio.lsp.messages.BaselineHover; import p.studio.lsp.messages.BaselineSemanticTokens; +import p.studio.lsp.messages.BaselineSignatureHelp; import p.studio.lsp.messages.BaselineServerDescription; import p.studio.lsp.messages.LspProjectContext; @@ -11,7 +13,11 @@ public interface LanguageServiceBridge { BaselineDocumentAnalysis analyzeDocument(LspProjectContext context, String documentUri, String text); - BaselineHover hover(LspProjectContext context, String documentUri, int line, int character); + BaselineCompletion completion(LspProjectContext context, String documentUri, String text, int line, int character); + + BaselineHover hover(LspProjectContext context, String documentUri, String text, int line, int character); + + BaselineSignatureHelp signatureHelp(LspProjectContext context, String documentUri, String text, int line, int character); BaselineSemanticTokens semanticTokens(LspProjectContext context, String documentUri, String text); diff --git a/prometeu-lsp/prometeu-lsp-v1/src/main/java/p/studio/lsp/services/compiler/CompilerLanguageServiceBridge.java b/prometeu-lsp/prometeu-lsp-v1/src/main/java/p/studio/lsp/services/compiler/CompilerLanguageServiceBridge.java index 8152a91d..4e971e0c 100644 --- a/prometeu-lsp/prometeu-lsp-v1/src/main/java/p/studio/lsp/services/compiler/CompilerLanguageServiceBridge.java +++ b/prometeu-lsp/prometeu-lsp-v1/src/main/java/p/studio/lsp/services/compiler/CompilerLanguageServiceBridge.java @@ -3,7 +3,10 @@ package p.studio.lsp.services.compiler; import org.apache.commons.lang3.StringUtils; import p.studio.compiler.FrontendRegistryService; import p.studio.compiler.messages.BuilderPipelineConfig; +import p.studio.compiler.messages.BuildingIssueSink; +import p.studio.compiler.messages.FrontendPhaseContext; import p.studio.compiler.messages.BuildingIssue; +import p.studio.compiler.messages.HostAdmissionContext; import p.studio.compiler.models.AnalysisSnapshot; import p.studio.compiler.models.BuilderPipelineContext; import p.studio.compiler.models.FrontendEditorPaletteSpec; @@ -14,20 +17,33 @@ import p.studio.compiler.models.FrontendSemanticToken; import p.studio.compiler.models.FrontendTokenStyleSpec; import p.studio.compiler.models.FrontendVisualThemeSpec; import p.studio.compiler.source.identifiers.FileId; +import p.studio.compiler.services.PBSFrontendPhaseService; +import p.studio.compiler.workspaces.AssetSurfaceContextLoader; import p.studio.compiler.utilities.SourceProviderFactory; import p.studio.compiler.workspaces.BuilderPipelineService; +import p.studio.compiler.pbs.semantics.PbsEditorialCompletionCandidate; +import p.studio.compiler.pbs.semantics.PbsEditorialResolvedSymbol; +import p.studio.compiler.pbs.semantics.PbsEditorialSignature; +import p.studio.compiler.pbs.semantics.PbsEditorialSymbolKind; +import p.studio.compiler.pbs.semantics.PbsEditorialSupportService; import p.studio.lsp.messages.*; import p.studio.lsp.services.LanguageServiceBridge; import p.studio.utilities.logs.LogAggregator; +import p.studio.utilities.structures.ReadOnlyList; import java.net.URI; import java.nio.file.Path; import java.util.ArrayList; import java.util.List; +import java.util.Locale; import java.util.Map; import java.util.Objects; +import java.util.Optional; public final class CompilerLanguageServiceBridge implements LanguageServiceBridge { + private final AssetSurfaceContextLoader assetSurfaceContextLoader = new AssetSurfaceContextLoader(); + private final PbsEditorialSupportService editorialSupportService = new PbsEditorialSupportService(); + @Override public BaselineServerDescription describeServer(final LspProjectContext context) { Objects.requireNonNull(context, "context"); @@ -38,6 +54,8 @@ public final class CompilerLanguageServiceBridge implements LanguageServiceBridg "0.1.0", context.languageId(), true, + true, + true, presentation.semanticKeys(), presentation.hostProjections().stream().map(this::mapSemanticHostProjection).toList(), presentation.themes().stream().map(this::mapVisualTheme).toList(), @@ -57,19 +75,76 @@ public final class CompilerLanguageServiceBridge implements LanguageServiceBridg } @Override - public BaselineHover hover( + public BaselineCompletion completion( final LspProjectContext context, final String documentUri, + final String text, final int line, final int character) { Objects.requireNonNull(context, "context"); - return new BaselineHover(""" - **Prometeu Studio LSP** - - Compiler-backed baseline. - - Semantic enrichment will be layered later. - """); + return editorialDocument(context, documentUri, text) + .map(document -> { + final int offset = new DocumentPositionMapper(document.text()).byteOffsetOf(line, character); + final List candidates = editorialSupportService.completion( + document.text(), + document.ast(), + document.supplementalTopDecls(), + document.feSurfaceContext(), + offset); + return new BaselineCompletion( + false, + candidates.stream().map(this::mapCompletionItem).toList()); + }) + .orElseGet(() -> new BaselineCompletion(false, List.of())); + } + + @Override + public BaselineHover hover( + final LspProjectContext context, + final String documentUri, + final String text, + final int line, + final int character) { + Objects.requireNonNull(context, "context"); + return editorialDocument(context, documentUri, text) + .flatMap(document -> { + final int offset = new DocumentPositionMapper(document.text()).byteOffsetOf(line, character); + return editorialSupportService.hover( + document.text(), + document.ast(), + document.supplementalTopDecls(), + document.feSurfaceContext(), + offset); + }) + .map(symbol -> new BaselineHover(formatHoverMarkdown(symbol))) + .orElseGet(() -> new BaselineHover("No symbol information.")); + } + + @Override + public BaselineSignatureHelp signatureHelp( + final LspProjectContext context, + final String documentUri, + final String text, + final int line, + final int character) { + Objects.requireNonNull(context, "context"); + return editorialDocument(context, documentUri, text) + .flatMap(document -> { + final int offset = new DocumentPositionMapper(document.text()).byteOffsetOf(line, character); + return editorialSupportService.signatureHelp( + document.text(), + document.ast(), + document.supplementalTopDecls(), + document.feSurfaceContext(), + offset); + }) + .map(signatureHelp -> new BaselineSignatureHelp( + signatureHelp.signatures().stream() + .map(signature -> new BaselineSignature(signature.label(), signature.parameterLabels(), "")) + .toList(), + signatureHelp.activeSignature(), + signatureHelp.activeParameter())) + .orElseGet(() -> new BaselineSignatureHelp(List.of(), 0, 0)); } @Override @@ -119,6 +194,71 @@ public final class CompilerLanguageServiceBridge implements LanguageServiceBridg return BuilderPipelineService.INSTANCE.analyze(pipelineContext, LogAggregator.empty()); } + private Optional editorialDocument( + final LspProjectContext context, + final String documentUri, + final String text) { + if (!"pbs".equals(context.languageId())) { + return Optional.empty(); + } + final Path documentPath = normalizeDocumentPath(documentUri); + final BuilderPipelineContext pipelineContext = BuilderPipelineContext.fromConfig( + new BuilderPipelineConfig( + false, + context.projectRoot().toString(), + "core-v1", + SourceProviderFactory.overlayUtf8(text == null ? Map.of() : Map.of(documentPath, text)))); + BuilderPipelineService.INSTANCE.analyze(pipelineContext, LogAggregator.empty()); + final FileId fileId = findFileId(pipelineContext, documentPath); + if (fileId == null) { + return Optional.empty(); + } + final FrontendPhaseContext frontendPhaseContext = new FrontendPhaseContext( + pipelineContext.resolvedWorkspace.graph().projectTable(), + pipelineContext.fileTable, + pipelineContext.resolvedWorkspace.stack(), + pipelineContext.resolvedWorkspace.stdlib(), + HostAdmissionContext.permissiveDefault(), + assetSurfaceContextLoader.load(pipelineContext.resolvedWorkspace.mainProject().getRootPath())); + final var semanticReadSurface = PBSFrontendPhaseService.semanticReadSurface( + frontendPhaseContext, + p.studio.compiler.source.diagnostics.DiagnosticSink.empty(), + BuildingIssueSink.empty()); + final var ast = semanticReadSurface.astByFile().get(fileId); + if (ast == null) { + return Optional.empty(); + } + return Optional.of(new EditorialDocument( + text == null ? readCurrentText(pipelineContext, fileId) : text, + ast, + semanticReadSurface.supplementalTopDeclsByFile().getOrDefault(fileId, ReadOnlyList.empty()), + frontendPhaseContext.feSurfaceContext())); + } + + private FileId findFileId( + final BuilderPipelineContext pipelineContext, + final Path documentPath) { + for (int fileIndex = 0; fileIndex < pipelineContext.fileTable.size(); fileIndex += 1) { + final FileId candidate = new FileId(fileIndex); + final var sourceHandle = pipelineContext.fileTable.get(candidate); + if (sourceHandle != null + && sourceHandle.getCanonPath().toAbsolutePath().normalize().equals(documentPath)) { + return candidate; + } + } + return null; + } + + private String readCurrentText( + final BuilderPipelineContext pipelineContext, + final FileId fileId) { + final var sourceHandle = pipelineContext.fileTable.get(fileId); + if (sourceHandle == null) { + return ""; + } + return sourceHandle.readUtf8().orElse(""); + } + private List mapDiagnostics( final AnalysisSnapshot snapshot, final Path documentPath, @@ -163,6 +303,14 @@ public final class CompilerLanguageServiceBridge implements LanguageServiceBridg return Path.of(URI.create(Objects.requireNonNull(documentUri, "documentUri"))).toAbsolutePath().normalize(); } + private BaselineCompletionItem mapCompletionItem(final PbsEditorialCompletionCandidate candidate) { + return new BaselineCompletionItem( + candidate.label(), + mapCompletionKind(candidate.kind()), + candidate.detail(), + candidate.origin()); + } + private BaselineVisualTheme mapVisualTheme(final FrontendVisualThemeSpec theme) { return new BaselineVisualTheme( theme.themeId(), @@ -210,4 +358,65 @@ public final class CompilerLanguageServiceBridge implements LanguageServiceBridg return FrontendRegistryService.getFrontendSpec(context.languageId()) .orElseThrow(() -> new IllegalArgumentException("no frontend registered for languageId: " + context.languageId())); } + + private BaselineCompletionItemKind mapCompletionKind(final PbsEditorialSymbolKind kind) { + return switch (kind) { + case KEYWORD -> BaselineCompletionItemKind.KEYWORD; + case LOCAL, PARAMETER -> BaselineCompletionItemKind.VARIABLE; + case FIELD -> BaselineCompletionItemKind.FIELD; + case FUNCTION -> BaselineCompletionItemKind.FUNCTION; + case METHOD -> BaselineCompletionItemKind.METHOD; + case CONSTRUCTOR -> BaselineCompletionItemKind.CONSTRUCTOR; + case STRUCT -> BaselineCompletionItemKind.STRUCT; + case BUILTIN_TYPE -> BaselineCompletionItemKind.BUILTIN_TYPE; + case SERVICE -> BaselineCompletionItemKind.SERVICE; + case HOST -> BaselineCompletionItemKind.HOST; + case CONTRACT -> BaselineCompletionItemKind.CONTRACT; + case CALLBACK -> BaselineCompletionItemKind.CALLBACK; + case ENUM -> BaselineCompletionItemKind.ENUM; + case ERROR -> BaselineCompletionItemKind.ERROR; + case GLOBAL -> BaselineCompletionItemKind.GLOBAL; + case CONST -> BaselineCompletionItemKind.CONST; + }; + } + + private String formatHoverMarkdown(final PbsEditorialResolvedSymbol symbol) { + final StringBuilder markdown = new StringBuilder(); + final List signatures = symbol.signatures(); + if (!signatures.isEmpty()) { + markdown.append("```pbs\n"); + for (int index = 0; index < signatures.size(); index += 1) { + if (index > 0) { + markdown.append('\n'); + } + markdown.append(signatures.get(index).label()); + } + markdown.append("\n```"); + } else if (!symbol.detail().isBlank()) { + markdown.append("```pbs\n").append(symbol.displayName()); + if (!symbol.detail().isBlank()) { + markdown.append(" : ").append(symbol.detail()); + } + markdown.append("\n```"); + } + final String kindLabel = symbol.kind().name().toLowerCase(Locale.ROOT).replace('_', ' '); + if (markdown.length() > 0) { + markdown.append("\n\n"); + } + markdown.append("**").append(kindLabel).append("**"); + if (!symbol.origin().isBlank()) { + markdown.append(" from `").append(symbol.origin()).append('`'); + } + if (!symbol.documentation().isBlank()) { + markdown.append("\n\n").append(symbol.documentation()); + } + return markdown.toString(); + } + + private record EditorialDocument( + String text, + p.studio.compiler.pbs.ast.PbsAst.File ast, + ReadOnlyList supplementalTopDecls, + p.studio.compiler.messages.FESurfaceContext feSurfaceContext) { + } } diff --git a/prometeu-lsp/prometeu-lsp-v1/src/main/java/p/studio/lsp/services/compiler/DocumentPositionMapper.java b/prometeu-lsp/prometeu-lsp-v1/src/main/java/p/studio/lsp/services/compiler/DocumentPositionMapper.java index 7c791003..449a7482 100644 --- a/prometeu-lsp/prometeu-lsp-v1/src/main/java/p/studio/lsp/services/compiler/DocumentPositionMapper.java +++ b/prometeu-lsp/prometeu-lsp-v1/src/main/java/p/studio/lsp/services/compiler/DocumentPositionMapper.java @@ -42,6 +42,40 @@ final class DocumentPositionMapper { return new DocumentPosition(line, character); } + int byteOffsetOf( + final int line, + final int character) { + if (line <= 0 && character <= 0) { + return 0; + } + int currentLine = 0; + int currentCharacter = 0; + int utf8Offset = 0; + for (int index = 0; index < text.length(); ) { + if (currentLine == line && currentCharacter >= character) { + return utf8Offset; + } + final int codePoint = text.codePointAt(index); + final int utf16Width = Character.charCount(codePoint); + final int utf8Width = utf8Length(codePoint); + if (currentLine == line && currentCharacter + utf16Width > character) { + return utf8Offset; + } + utf8Offset += utf8Width; + if (codePoint == '\n') { + if (currentLine == line) { + return utf8Offset - utf8Width; + } + currentLine += 1; + currentCharacter = 0; + } else { + currentCharacter += utf16Width; + } + index += utf16Width; + } + return utf8Offset; + } + private int utf8Length(final int codePoint) { if (codePoint <= 0x7F) { return 1; @@ -54,4 +88,4 @@ final class DocumentPositionMapper { } return 4; } -} \ No newline at end of file +} diff --git a/prometeu-lsp/prometeu-lsp-v1/src/main/java/p/studio/lsp/services/protocol/PrometeuTextDocumentService.java b/prometeu-lsp/prometeu-lsp-v1/src/main/java/p/studio/lsp/services/protocol/PrometeuTextDocumentService.java index 184f4054..ef4b139d 100644 --- a/prometeu-lsp/prometeu-lsp-v1/src/main/java/p/studio/lsp/services/protocol/PrometeuTextDocumentService.java +++ b/prometeu-lsp/prometeu-lsp-v1/src/main/java/p/studio/lsp/services/protocol/PrometeuTextDocumentService.java @@ -1,6 +1,7 @@ package p.studio.lsp.services.protocol; import org.eclipse.lsp4j.*; +import org.eclipse.lsp4j.jsonrpc.messages.Either; import org.eclipse.lsp4j.services.LanguageClient; import org.eclipse.lsp4j.services.TextDocumentService; import p.studio.lsp.messages.LspProjectContext; @@ -11,6 +12,7 @@ import java.util.Objects; import java.util.concurrent.ConcurrentHashMap; import java.util.concurrent.CompletableFuture; import java.util.concurrent.ConcurrentMap; +import java.util.List; public final class PrometeuTextDocumentService implements TextDocumentService { private final LspProjectContext project; @@ -70,15 +72,44 @@ public final class PrometeuTextDocumentService implements TextDocumentService { languageServiceBridge.onSave(project, params.getTextDocument().getUri()))); } + @Override + public CompletableFuture, CompletionList>> completion(final CompletionParams params) { + final String uri = params.getTextDocument().getUri(); + final String text = documentTextByUri.get(uri); + return CompletableFuture.completedFuture(Either.forRight(protocolMessageMapper.mapCompletion( + languageServiceBridge.completion( + project, + uri, + text, + params.getPosition().getLine(), + params.getPosition().getCharacter())))); + } + @Override public CompletableFuture hover(final HoverParams params) { + final String uri = params.getTextDocument().getUri(); + final String text = documentTextByUri.get(uri); return CompletableFuture.completedFuture(protocolMessageMapper.mapHover(languageServiceBridge.hover( project, - params.getTextDocument().getUri(), + uri, + text, params.getPosition().getLine(), params.getPosition().getCharacter()))); } + @Override + public CompletableFuture signatureHelp(final SignatureHelpParams params) { + final String uri = params.getTextDocument().getUri(); + final String text = documentTextByUri.get(uri); + return CompletableFuture.completedFuture(protocolMessageMapper.mapSignatureHelp( + languageServiceBridge.signatureHelp( + project, + uri, + text, + params.getPosition().getLine(), + params.getPosition().getCharacter()))); + } + @Override public CompletableFuture semanticTokensFull(final SemanticTokensParams params) { final String uri = params.getTextDocument().getUri(); diff --git a/prometeu-lsp/prometeu-lsp-v1/src/main/java/p/studio/lsp/services/protocol/mapping/Lsp4jProtocolMessageMapper.java b/prometeu-lsp/prometeu-lsp-v1/src/main/java/p/studio/lsp/services/protocol/mapping/Lsp4jProtocolMessageMapper.java index 48caa92a..7b3d548c 100644 --- a/prometeu-lsp/prometeu-lsp-v1/src/main/java/p/studio/lsp/services/protocol/mapping/Lsp4jProtocolMessageMapper.java +++ b/prometeu-lsp/prometeu-lsp-v1/src/main/java/p/studio/lsp/services/protocol/mapping/Lsp4jProtocolMessageMapper.java @@ -24,6 +24,18 @@ public final class Lsp4jProtocolMessageMapper implements ProtocolMessageMapper { capabilities.setTextDocumentSync(syncOptions); capabilities.setHoverProvider(description.hoverSupported()); + if (description.completionSupported()) { + final CompletionOptions completionOptions = new CompletionOptions(); + completionOptions.setResolveProvider(false); + completionOptions.setTriggerCharacters(List.of(".")); + capabilities.setCompletionProvider(completionOptions); + } + if (description.signatureHelpSupported()) { + final SignatureHelpOptions signatureHelpOptions = new SignatureHelpOptions(); + signatureHelpOptions.setTriggerCharacters(List.of("(", ",")); + signatureHelpOptions.setRetriggerCharacters(List.of(",")); + capabilities.setSignatureHelpProvider(signatureHelpOptions); + } final SemanticTokensWithRegistrationOptions semanticTokens = new SemanticTokensWithRegistrationOptions(); semanticTokens.setLegend(new SemanticTokensLegend(description.semanticTokenTypes(), List.of())); semanticTokens.setFull(true); @@ -71,6 +83,38 @@ public final class Lsp4jProtocolMessageMapper implements ProtocolMessageMapper { return result; } + @Override + public CompletionList mapCompletion(final BaselineCompletion completion) { + final CompletionList list = new CompletionList(); + list.setIsIncomplete(completion.incomplete()); + list.setItems(completion.items().stream().map(this::mapCompletionItem).toList()); + return list; + } + + @Override + public SignatureHelp mapSignatureHelp(final BaselineSignatureHelp signatureHelp) { + final SignatureHelp result = new SignatureHelp(); + result.setActiveSignature(signatureHelp.activeSignature()); + result.setActiveParameter(signatureHelp.activeParameter()); + result.setSignatures(signatureHelp.signatures().stream().map(signature -> { + final SignatureInformation information = new SignatureInformation(); + information.setLabel(signature.label()); + if (!signature.documentation().isBlank()) { + final MarkupContent content = new MarkupContent(); + content.setKind(MarkupKind.MARKDOWN); + content.setValue(signature.documentation()); + information.setDocumentation(content); + } + information.setParameters(signature.parameters().stream().map(parameter -> { + final ParameterInformation parameterInformation = new ParameterInformation(); + parameterInformation.setLabel(parameter); + return parameterInformation; + }).toList()); + return information; + }).toList()); + return result; + } + @Override public SemanticTokens mapSemanticTokens(final BaselineSemanticTokens semanticTokens) { final List orderedTokens = new ArrayList<>(semanticTokens.tokens()); @@ -127,6 +171,39 @@ public final class Lsp4jProtocolMessageMapper implements ProtocolMessageMapper { return diagnostic; } + private CompletionItem mapCompletionItem(final BaselineCompletionItem item) { + final CompletionItem completionItem = new CompletionItem(); + completionItem.setLabel(item.label()); + completionItem.setKind(mapCompletionItemKind(item.kind())); + if (!item.detail().isBlank()) { + completionItem.setDetail(item.detail()); + } + if (!item.documentation().isBlank()) { + final MarkupContent content = new MarkupContent(); + content.setKind(MarkupKind.MARKDOWN); + content.setValue(item.documentation()); + completionItem.setDocumentation(content); + } + return completionItem; + } + + private CompletionItemKind mapCompletionItemKind(final BaselineCompletionItemKind kind) { + return switch (kind) { + case KEYWORD -> CompletionItemKind.Keyword; + case VARIABLE -> CompletionItemKind.Variable; + case FIELD -> CompletionItemKind.Field; + case FUNCTION -> CompletionItemKind.Function; + case METHOD -> CompletionItemKind.Method; + case CONSTRUCTOR -> CompletionItemKind.Constructor; + case STRUCT, BUILTIN_TYPE -> CompletionItemKind.Struct; + case SERVICE, HOST, CONTRACT -> CompletionItemKind.Interface; + case CALLBACK -> CompletionItemKind.Function; + case ENUM -> CompletionItemKind.Enum; + case ERROR -> CompletionItemKind.EnumMember; + case GLOBAL, CONST -> CompletionItemKind.Constant; + }; + } + private DiagnosticSeverity mapSeverity(final BaselineIssueSeverity severity) { return switch (severity) { diff --git a/prometeu-lsp/prometeu-lsp-v1/src/main/java/p/studio/lsp/services/protocol/mapping/ProtocolMessageMapper.java b/prometeu-lsp/prometeu-lsp-v1/src/main/java/p/studio/lsp/services/protocol/mapping/ProtocolMessageMapper.java index 18172125..7897adae 100644 --- a/prometeu-lsp/prometeu-lsp-v1/src/main/java/p/studio/lsp/services/protocol/mapping/ProtocolMessageMapper.java +++ b/prometeu-lsp/prometeu-lsp-v1/src/main/java/p/studio/lsp/services/protocol/mapping/ProtocolMessageMapper.java @@ -4,11 +4,15 @@ import org.eclipse.lsp4j.Hover; import org.eclipse.lsp4j.InitializeResult; import org.eclipse.lsp4j.MessageParams; import org.eclipse.lsp4j.PublishDiagnosticsParams; +import org.eclipse.lsp4j.SignatureHelp; import org.eclipse.lsp4j.SemanticTokens; import p.studio.lsp.messages.BaselineDocumentAnalysis; +import p.studio.lsp.messages.BaselineCompletion; import p.studio.lsp.messages.BaselineHover; import p.studio.lsp.messages.BaselineSemanticTokens; +import p.studio.lsp.messages.BaselineSignatureHelp; import p.studio.lsp.messages.BaselineServerDescription; +import org.eclipse.lsp4j.CompletionList; public interface ProtocolMessageMapper { InitializeResult mapInitializeResult(BaselineServerDescription description); @@ -19,6 +23,10 @@ public interface ProtocolMessageMapper { Hover mapHover(BaselineHover hover); + CompletionList mapCompletion(BaselineCompletion completion); + + SignatureHelp mapSignatureHelp(BaselineSignatureHelp signatureHelp); + SemanticTokens mapSemanticTokens(BaselineSemanticTokens semanticTokens); MessageParams mapInfoMessage(String message); diff --git a/prometeu-lsp/prometeu-lsp-v1/src/test/java/p/studio/lsp/services/compiler/CompilerLanguageServiceBridgeTest.java b/prometeu-lsp/prometeu-lsp-v1/src/test/java/p/studio/lsp/services/compiler/CompilerLanguageServiceBridgeTest.java index 87f49fbb..319dc6ef 100644 --- a/prometeu-lsp/prometeu-lsp-v1/src/test/java/p/studio/lsp/services/compiler/CompilerLanguageServiceBridgeTest.java +++ b/prometeu-lsp/prometeu-lsp-v1/src/test/java/p/studio/lsp/services/compiler/CompilerLanguageServiceBridgeTest.java @@ -98,6 +98,71 @@ class CompilerLanguageServiceBridgeTest { assertTrue(semanticTokens.tokens().stream().anyMatch(token -> token.semanticKey().equals("pbs-builtin-type"))); } + @Test + void completionHoverAndSignatureHelpUseCompilerBackedEditorialResolution() { + final Path projectRoot = findRepoRoot(Path.of("").toAbsolutePath().normalize()) + .resolve("test-projects") + .resolve("main") + .toAbsolutePath() + .normalize(); + final Path documentPath = projectRoot.resolve("src").resolve("main.pbs"); + final String overlay = """ + declare struct Vec() { + fn blend(dx: int, dy: int) -> int { return dx; } + } + + fn mix(left: int, right: int) -> int { return left; } + + fn frame(vec: Vec) -> void { + mix(1, 2); + vec.blend(1, 2); + new Vec(); + } + """; + final CompilerLanguageServiceBridge bridge = new CompilerLanguageServiceBridge(); + final LspProjectContext context = new LspProjectContext("main", "pbs", projectRoot); + final DocumentPositionMapper mapper = new DocumentPositionMapper(overlay); + final var completionPosition = mapper.positionOf(overlay.indexOf("mix(1, 2);")); + final var hoverPosition = mapper.positionOf(overlay.indexOf("blend(1, 2);")); + final var functionSignaturePosition = mapper.positionOf(overlay.indexOf("2);")); + final var constructorSignaturePosition = mapper.positionOf(overlay.indexOf("Vec();") + 4); + + final var completion = bridge.completion( + context, + documentPath.toUri().toString(), + overlay, + completionPosition.line(), + completionPosition.character()); + assertTrue(completion.items().stream().anyMatch(item -> item.label().equals("mix"))); + assertTrue(completion.items().stream().anyMatch(item -> item.label().equals("vec"))); + + final var hover = bridge.hover( + context, + documentPath.toUri().toString(), + overlay, + hoverPosition.line(), + hoverPosition.character()); + assertTrue(hover.markdown().contains("blend(arg0: int, arg1: int) -> int")); + assertTrue(hover.markdown().contains("**method**")); + + final var functionSignatureHelp = bridge.signatureHelp( + context, + documentPath.toUri().toString(), + overlay, + functionSignaturePosition.line(), + functionSignaturePosition.character()); + assertEquals(1, functionSignatureHelp.activeParameter()); + assertEquals("mix(left: int, right: int) -> int", functionSignatureHelp.signatures().getFirst().label()); + + final var constructorSignatureHelp = bridge.signatureHelp( + context, + documentPath.toUri().toString(), + overlay, + constructorSignaturePosition.line(), + constructorSignaturePosition.character()); + assertEquals("Vec()", constructorSignatureHelp.signatures().getFirst().label()); + } + @Test void describeServerPublishesFrontendVisualThemes() { final CompilerLanguageServiceBridge bridge = new CompilerLanguageServiceBridge(); @@ -106,6 +171,8 @@ class CompilerLanguageServiceBridgeTest { assertEquals("pbs", description.frontendLanguageId()); assertEquals("pbs-default", description.activeVisualThemeId()); + assertTrue(description.completionSupported()); + assertTrue(description.signatureHelpSupported()); assertEquals(1, description.semanticHostProjections().size()); assertEquals("vscode", description.semanticHostProjections().getFirst().hostId()); assertTrue(description.semanticHostProjections().getFirst().tokenProjections().stream() diff --git a/prometeu-lsp/prometeu-lsp-v1/src/test/java/p/studio/lsp/services/protocol/PrometeuLanguageServerTest.java b/prometeu-lsp/prometeu-lsp-v1/src/test/java/p/studio/lsp/services/protocol/PrometeuLanguageServerTest.java index 5b4fc14d..ae67bbb9 100644 --- a/prometeu-lsp/prometeu-lsp-v1/src/test/java/p/studio/lsp/services/protocol/PrometeuLanguageServerTest.java +++ b/prometeu-lsp/prometeu-lsp-v1/src/test/java/p/studio/lsp/services/protocol/PrometeuLanguageServerTest.java @@ -6,16 +6,22 @@ import org.eclipse.lsp4j.InitializeResult; import org.eclipse.lsp4j.InitializedParams; import org.eclipse.lsp4j.MessageParams; import org.eclipse.lsp4j.PublishDiagnosticsParams; +import org.eclipse.lsp4j.SignatureHelp; import org.eclipse.lsp4j.SemanticTokens; import org.eclipse.lsp4j.jsonrpc.ResponseErrorException; import org.eclipse.lsp4j.services.LanguageClient; import org.eclipse.lsp4j.services.TextDocumentService; import org.junit.jupiter.api.Test; +import p.studio.lsp.messages.BaselineCompletion; +import p.studio.lsp.messages.BaselineCompletionItem; +import p.studio.lsp.messages.BaselineCompletionItemKind; import p.studio.lsp.messages.BaselineDocumentAnalysis; import p.studio.lsp.messages.BaselineEditorPalette; import p.studio.lsp.messages.BaselineHover; import p.studio.lsp.messages.BaselineSemanticHostProjection; import p.studio.lsp.messages.BaselineSemanticHostProjectionEntry; +import p.studio.lsp.messages.BaselineSignature; +import p.studio.lsp.messages.BaselineSignatureHelp; import p.studio.lsp.messages.BaselineSemanticTokens; import p.studio.lsp.messages.BaselineServerDescription; import p.studio.lsp.messages.BaselineTokenStyle; @@ -90,6 +96,8 @@ class PrometeuLanguageServerTest { "1", "pbs", true, + true, + true, List.of(), List.of(new BaselineSemanticHostProjection( "vscode", @@ -118,10 +126,35 @@ class PrometeuLanguageServerTest { } @Override - public BaselineHover hover(final LspProjectContext project, final String documentUri, final int line, final int character) { + public BaselineCompletion completion( + final LspProjectContext project, + final String documentUri, + final String text, + final int line, + final int character) { + return new BaselineCompletion(false, List.of(new BaselineCompletionItem("demo", BaselineCompletionItemKind.FUNCTION, "", ""))); + } + + @Override + public BaselineHover hover( + final LspProjectContext project, + final String documentUri, + final String text, + final int line, + final int character) { return new BaselineHover("hover"); } + @Override + public BaselineSignatureHelp signatureHelp( + final LspProjectContext project, + final String documentUri, + final String text, + final int line, + final int character) { + return new BaselineSignatureHelp(List.of(new BaselineSignature("demo()", List.of(), "")), 0, 0); + } + @Override public BaselineSemanticTokens semanticTokens(final LspProjectContext context, final String documentUri, final String text) { return new BaselineSemanticTokens(List.of(), List.of()); @@ -158,6 +191,16 @@ class PrometeuLanguageServerTest { throw new UnsupportedOperationException(); } + @Override + public org.eclipse.lsp4j.CompletionList mapCompletion(final BaselineCompletion completion) { + throw new UnsupportedOperationException(); + } + + @Override + public SignatureHelp mapSignatureHelp(final BaselineSignatureHelp signatureHelp) { + throw new UnsupportedOperationException(); + } + @Override public SemanticTokens mapSemanticTokens(final BaselineSemanticTokens semanticTokens) { throw new UnsupportedOperationException(); diff --git a/prometeu-lsp/prometeu-lsp-v1/src/test/java/p/studio/lsp/services/protocol/mapping/Lsp4jProtocolMessageMapperTest.java b/prometeu-lsp/prometeu-lsp-v1/src/test/java/p/studio/lsp/services/protocol/mapping/Lsp4jProtocolMessageMapperTest.java index bf6a9b24..78516e5b 100644 --- a/prometeu-lsp/prometeu-lsp-v1/src/test/java/p/studio/lsp/services/protocol/mapping/Lsp4jProtocolMessageMapperTest.java +++ b/prometeu-lsp/prometeu-lsp-v1/src/test/java/p/studio/lsp/services/protocol/mapping/Lsp4jProtocolMessageMapperTest.java @@ -1,10 +1,16 @@ package p.studio.lsp.services.protocol.mapping; import org.eclipse.lsp4j.InitializeResult; +import org.eclipse.lsp4j.jsonrpc.messages.Either; import org.junit.jupiter.api.Test; +import p.studio.lsp.messages.BaselineCompletion; +import p.studio.lsp.messages.BaselineCompletionItem; +import p.studio.lsp.messages.BaselineCompletionItemKind; import p.studio.lsp.messages.BaselineEditorPalette; import p.studio.lsp.messages.BaselineSemanticHostProjection; import p.studio.lsp.messages.BaselineSemanticHostProjectionEntry; +import p.studio.lsp.messages.BaselineSignature; +import p.studio.lsp.messages.BaselineSignatureHelp; import p.studio.lsp.messages.BaselineServerDescription; import p.studio.lsp.messages.BaselineTokenStyle; import p.studio.lsp.messages.BaselineVisualTheme; @@ -14,6 +20,7 @@ import java.util.Map; import static org.junit.jupiter.api.Assertions.assertEquals; import static org.junit.jupiter.api.Assertions.assertInstanceOf; +import static org.junit.jupiter.api.Assertions.assertTrue; final class Lsp4jProtocolMessageMapperTest { @@ -25,6 +32,8 @@ final class Lsp4jProtocolMessageMapperTest { "1", "pbs", true, + true, + true, List.of("demo-keyword"), List.of(new BaselineSemanticHostProjection( "vscode", @@ -43,6 +52,9 @@ final class Lsp4jProtocolMessageMapperTest { final InitializeResult result = mapper.mapInitializeResult(description); + assertEquals(List.of("."), result.getCapabilities().getCompletionProvider().getTriggerCharacters()); + assertEquals(List.of("(", ","), result.getCapabilities().getSignatureHelpProvider().getTriggerCharacters()); + final var experimental = assertInstanceOf(Map.class, result.getCapabilities().getExperimental()); final var semanticPayload = assertInstanceOf(Map.class, experimental.get("prometeuSemanticHostProjections")); assertEquals("pbs", semanticPayload.get("frontendLanguageId")); @@ -59,4 +71,33 @@ final class Lsp4jProtocolMessageMapperTest { assertEquals(List.of("declaration"), firstTokenProjection.get("hostTokenModifiers")); assertEquals("variable", firstTokenProjection.get("fallbackTokenType")); } + + @Test + void completionAndSignatureHelpMapToLspPayloads() { + final var mapper = new Lsp4jProtocolMessageMapper(); + + final var completion = mapper.mapCompletion(new BaselineCompletion( + false, + List.of(new BaselineCompletionItem( + "blend", + BaselineCompletionItemKind.METHOD, + "blend(dx: int, dy: int) -> int", + "method docs")))); + assertEquals(1, completion.getItems().size()); + assertEquals("blend", completion.getItems().getFirst().getLabel()); + assertEquals("blend(dx: int, dy: int) -> int", completion.getItems().getFirst().getDetail()); + final var documentation = assertInstanceOf(Either.class, completion.getItems().getFirst().getDocumentation()); + assertTrue(documentation.isRight()); + + final var signatureHelp = mapper.mapSignatureHelp(new BaselineSignatureHelp( + List.of(new BaselineSignature( + "mix(left: int, right: int) -> int", + List.of("left: int", "right: int"), + "")), + 0, + 1)); + assertEquals(1, signatureHelp.getSignatures().size()); + assertEquals("mix(left: int, right: int) -> int", signatureHelp.getSignatures().getFirst().getLabel()); + assertEquals(1, signatureHelp.getActiveParameter()); + } } -- 2.47.2 From 54339a95b89d6ab55d45f9e8e36fa2464eff68f2 Mon Sep 17 00:00:00 2001 From: bQUARKz Date: Fri, 8 May 2026 10:15:17 +0100 Subject: [PATCH 36/37] implements PLN-0077 --- .../PrometeuTextDocumentServiceTest.java | 212 ++++++++++++++++++ 1 file changed, 212 insertions(+) create mode 100644 prometeu-lsp/prometeu-lsp-v1/src/test/java/p/studio/lsp/services/protocol/PrometeuTextDocumentServiceTest.java diff --git a/prometeu-lsp/prometeu-lsp-v1/src/test/java/p/studio/lsp/services/protocol/PrometeuTextDocumentServiceTest.java b/prometeu-lsp/prometeu-lsp-v1/src/test/java/p/studio/lsp/services/protocol/PrometeuTextDocumentServiceTest.java new file mode 100644 index 00000000..05908c78 --- /dev/null +++ b/prometeu-lsp/prometeu-lsp-v1/src/test/java/p/studio/lsp/services/protocol/PrometeuTextDocumentServiceTest.java @@ -0,0 +1,212 @@ +package p.studio.lsp.services.protocol; + +import org.eclipse.lsp4j.CompletionItem; +import org.eclipse.lsp4j.CompletionList; +import org.eclipse.lsp4j.CompletionParams; +import org.eclipse.lsp4j.DidOpenTextDocumentParams; +import org.eclipse.lsp4j.Hover; +import org.eclipse.lsp4j.HoverParams; +import org.eclipse.lsp4j.MarkupContent; +import org.eclipse.lsp4j.Position; +import org.eclipse.lsp4j.SignatureHelp; +import org.eclipse.lsp4j.SignatureHelpParams; +import org.eclipse.lsp4j.TextDocumentIdentifier; +import org.eclipse.lsp4j.TextDocumentItem; +import org.junit.jupiter.api.Test; +import p.studio.lsp.messages.BaselineCompletion; +import p.studio.lsp.messages.BaselineCompletionItem; +import p.studio.lsp.messages.BaselineCompletionItemKind; +import p.studio.lsp.messages.BaselineDocumentAnalysis; +import p.studio.lsp.messages.BaselineHover; +import p.studio.lsp.messages.BaselineSemanticTokens; +import p.studio.lsp.messages.BaselineServerDescription; +import p.studio.lsp.messages.BaselineSignature; +import p.studio.lsp.messages.BaselineSignatureHelp; +import p.studio.lsp.messages.LspProjectContext; +import p.studio.lsp.services.LanguageServiceBridge; +import p.studio.lsp.services.protocol.mapping.ProtocolMessageMapper; + +import java.nio.file.Path; +import java.util.List; + +import static org.junit.jupiter.api.Assertions.assertEquals; +import static org.junit.jupiter.api.Assertions.assertSame; +import static org.junit.jupiter.api.Assertions.assertTrue; + +final class PrometeuTextDocumentServiceTest { + + @Test + void shouldPassOpenDocumentOverlayToCompletionHoverAndSignatureHelp() { + final var bridge = new RecordingBridge(); + final var mapper = new RecordingMapper(); + final var service = new PrometeuTextDocumentService( + new LspProjectContext("main", "pbs", Path.of(".")), + bridge, + mapper); + final String uri = Path.of("demo.pbs").toUri().toString(); + final String text = """ + fn frame() -> void { + demo(); + } + """; + + final var openParams = new DidOpenTextDocumentParams(new TextDocumentItem(uri, "pbs", 1, text)); + service.didOpen(openParams); + + final var completion = service.completion(new CompletionParams( + new TextDocumentIdentifier(uri), + new Position(1, 2))).join(); + final var completionList = completion.getRight(); + assertSame(mapper.completionList, completionList); + assertEquals(text, bridge.lastCompletionText); + assertEquals(1, bridge.lastCompletionLine); + assertEquals(2, bridge.lastCompletionCharacter); + + final Hover hover = service.hover(new HoverParams( + new TextDocumentIdentifier(uri), + new Position(1, 4))).join(); + final var hoverContent = (MarkupContent) hover.getContents().getRight(); + assertEquals("hover", hoverContent.getValue()); + assertEquals(text, bridge.lastHoverText); + + final SignatureHelp signatureHelp = service.signatureHelp(new SignatureHelpParams( + new TextDocumentIdentifier(uri), + new Position(1, 6))).join(); + assertSame(mapper.signatureHelp, signatureHelp); + assertEquals(text, bridge.lastSignatureHelpText); + assertEquals(1, bridge.lastSignatureHelpLine); + assertEquals(6, bridge.lastSignatureHelpCharacter); + assertTrue(mapper.mappedSignatureHelp.signatures().getFirst().label().contains("demo")); + } + + private static final class RecordingBridge implements LanguageServiceBridge { + private String lastCompletionText; + private int lastCompletionLine; + private int lastCompletionCharacter; + private String lastHoverText; + private String lastSignatureHelpText; + private int lastSignatureHelpLine; + private int lastSignatureHelpCharacter; + + @Override + public BaselineServerDescription describeServer(final LspProjectContext context) { + throw new UnsupportedOperationException(); + } + + @Override + public BaselineDocumentAnalysis analyzeDocument(final LspProjectContext context, final String documentUri, final String text) { + return new BaselineDocumentAnalysis(List.of()); + } + + @Override + public BaselineCompletion completion( + final LspProjectContext context, + final String documentUri, + final String text, + final int line, + final int character) { + lastCompletionText = text; + lastCompletionLine = line; + lastCompletionCharacter = character; + return new BaselineCompletion(false, List.of( + new BaselineCompletionItem("demo", BaselineCompletionItemKind.FUNCTION, "", ""))); + } + + @Override + public BaselineHover hover( + final LspProjectContext context, + final String documentUri, + final String text, + final int line, + final int character) { + lastHoverText = text; + return new BaselineHover("hover"); + } + + @Override + public BaselineSignatureHelp signatureHelp( + final LspProjectContext context, + final String documentUri, + final String text, + final int line, + final int character) { + lastSignatureHelpText = text; + lastSignatureHelpLine = line; + lastSignatureHelpCharacter = character; + return new BaselineSignatureHelp(List.of( + new BaselineSignature("demo()", List.of(), "")), 0, 0); + } + + @Override + public BaselineSemanticTokens semanticTokens(final LspProjectContext context, final String documentUri, final String text) { + return new BaselineSemanticTokens(List.of(), List.of()); + } + + @Override + public String onSave(final LspProjectContext context, final String documentUri) { + return "saved"; + } + } + + private static final class RecordingMapper implements ProtocolMessageMapper { + private final CompletionList completionList = new CompletionList(false, List.of(new CompletionItem("demo"))); + private final SignatureHelp signatureHelp = new SignatureHelp(); + private BaselineSignatureHelp mappedSignatureHelp; + + @Override + public org.eclipse.lsp4j.InitializeResult mapInitializeResult(final BaselineServerDescription description) { + throw new UnsupportedOperationException(); + } + + @Override + public org.eclipse.lsp4j.PublishDiagnosticsParams mapDiagnostics( + final String uri, + final BaselineDocumentAnalysis analysis) { + throw new UnsupportedOperationException(); + } + + @Override + public org.eclipse.lsp4j.PublishDiagnosticsParams emptyDiagnostics(final String uri) { + throw new UnsupportedOperationException(); + } + + @Override + public Hover mapHover(final BaselineHover hover) { + final var content = new MarkupContent(); + content.setKind("markdown"); + content.setValue(hover.markdown()); + return new Hover(content); + } + + @Override + public CompletionList mapCompletion(final BaselineCompletion completion) { + return completionList; + } + + @Override + public SignatureHelp mapSignatureHelp(final BaselineSignatureHelp signatureHelp) { + this.mappedSignatureHelp = signatureHelp; + return this.signatureHelp; + } + + @Override + public org.eclipse.lsp4j.SemanticTokens mapSemanticTokens(final BaselineSemanticTokens semanticTokens) { + throw new UnsupportedOperationException(); + } + + @Override + public org.eclipse.lsp4j.MessageParams mapInfoMessage(final String message) { + throw new UnsupportedOperationException(); + } + + @Override + public org.eclipse.lsp4j.MessageParams mapErrorMessage(final String message) { + throw new UnsupportedOperationException(); + } + + @Override + public org.eclipse.lsp4j.MessageParams mapWarningMessage(final String message) { + throw new UnsupportedOperationException(); + } + } +} -- 2.47.2 From 2f289b9425af687d557cabaa349e5e28255cbeed Mon Sep 17 00:00:00 2001 From: bQUARKz Date: Fri, 8 May 2026 10:30:54 +0100 Subject: [PATCH 37/37] update gitignore --- .../FrontendVisualThemeCssRendererTest.java | 25 - .../main/assets/.prometeu/cache.json | 786 +++++++++--------- tools/vscode-extension/.gitignore | 5 +- 3 files changed, 397 insertions(+), 419 deletions(-) delete mode 100644 prometeu-studio/src/test/java/p/studio/utilities/FrontendVisualThemeCssRendererTest.java diff --git a/prometeu-studio/src/test/java/p/studio/utilities/FrontendVisualThemeCssRendererTest.java b/prometeu-studio/src/test/java/p/studio/utilities/FrontendVisualThemeCssRendererTest.java deleted file mode 100644 index 3f4b2a17..00000000 --- a/prometeu-studio/src/test/java/p/studio/utilities/FrontendVisualThemeCssRendererTest.java +++ /dev/null @@ -1,25 +0,0 @@ -package p.studio.utilities; - -import org.junit.jupiter.api.Test; -import p.studio.compiler.PBSDefinitions; - -import static org.junit.jupiter.api.Assertions.assertTrue; - -class FrontendVisualThemeCssRendererTest { - - @Test - void rendersLegacyCompatibleCssFromStructuredFrontendTheme() { - final FrontendVisualThemeCssRenderer renderer = new FrontendVisualThemeCssRenderer(); - - final String css = renderer.renderDefaultTheme( - PBSDefinitions.PBS.getLanguageId(), - PBSDefinitions.PBS.getSemanticPresentation()); - - assertTrue(css.contains(".editor-workspace-code-area-type-pbs")); - assertTrue(css.contains(".text.editor-semantic-pbs-keyword")); - assertTrue(css.contains("-fx-fill: #569cd6;")); - assertTrue(css.contains("-fx-font-style: italic;")); - assertTrue(css.contains(".editor-workspace-status-chip-type-pbs")); - assertTrue(css.contains("-fx-border-color: #a47dff;")); - } -} diff --git a/test-projects/main/assets/.prometeu/cache.json b/test-projects/main/assets/.prometeu/cache.json index 0a8c0fad..174130e2 100644 --- a/test-projects/main/assets/.prometeu/cache.json +++ b/test-projects/main/assets/.prometeu/cache.json @@ -24,14 +24,14 @@ "last_modified" : 1774359772403, "fingerprint" : "eeb7cc665386299403b7be1c272375d5077f3647c587f8033aa8c9275f840562", "metadata" : { + "palette" : { + "originalArgb8888" : [ -265674 ], + "convertedRgb565" : [ -122 ] + }, "tile" : { "width" : 32, "height" : 32, "paletteIndices" : "AQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAAAAAAAAAAABAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEAAAAAAAAAAAEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQAAAAAAAAAAAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAAAAAAAAAAABAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEAAAAAAAAAAAEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQAAAAAAAAAAAQEBAQEBAQEBAQEBAAAAAAAAAAAAAAAAAAAAAAAAAAABAQEBAQEBAQEBAQEAAAAAAAAAAAAAAAAAAAAAAAAAAAEBAQEBAQEBAQEBAQAAAAAAAAAAAAAAAAAAAAAAAAAAAQEBAQEBAQEBAQEBAAAAAAAAAAAAAAAAAAAAAAAAAAABAQEBAQEBAQEBAQEAAAAAAAAAAAAAAAAAAAAAAAAAAAEBAQEBAQEBAQEBAQAAAAAAAAAAAAAAAAAAAAAAAAAAAQEBAQEBAQEBAQEBAAAAAAAAAAAAAAAAAAAAAAAAAAABAQEBAQEBAQEBAQEAAAAAAAAAAAAAAAAAAAAAAAAAAAEBAQEBAQEBAQEBAQAAAAAAAAAAAAAAAAAAAQEBAQEBAQEBAQEBAQEBAQEBAAAAAAAAAAAAAAAAAAABAQEBAQEBAQEBAQEBAQEBAQEAAAAAAAAAAAAAAAAAAAEBAQEBAQEBAQEBAQEBAQEBAQAAAAAAAAAAAAAAAAAAAQEBAQEBAQEBAQEBAAAAAAAAAAAAAAAAAAAAAAAAAAABAQEBAQEBAQEBAQEAAAAAAAAAAAAAAAAAAAAAAAAAAAEBAQEBAQEBAQEBAQAAAAAAAAAAAAAAAAAAAQEBAQEBAQEBAQEBAQEBAQEBAAAAAAAAAAAAAAAAAAABAQEBAQEBAQEBAQEBAQEBAQEAAAAAAAAAAAAAAAAAAAEBAQEBAQEBAQEBAQEBAQEBAQAAAAAAAAAAAAAAAAAAAQEBAQEBAQEBAQEBAQEBAQEBAAAAAAAAAAAAAAAAAAABAQEBAQEBAQEBAQEBAQEBAQEAAAAAAAAAAAAAAAAAAAEBAQEBAQEBAQEBAQ==" - }, - "palette" : { - "originalArgb8888" : [ -265674 ], - "convertedRgb565" : [ -122 ] } }, "diagnostics" : [ ] @@ -42,14 +42,14 @@ "last_modified" : 1774359772405, "fingerprint" : "eeb7cc665386299403b7be1c272375d5077f3647c587f8033aa8c9275f840562", "metadata" : { + "palette" : { + "originalArgb8888" : [ -265674 ], + "convertedRgb565" : [ -122 ] + }, "tile" : { "width" : 32, "height" : 32, "paletteIndices" : "AQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAAAAAAAAAAABAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEAAAAAAAAAAAEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQAAAAAAAAAAAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAAAAAAAAAAABAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEAAAAAAAAAAAEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQAAAAAAAAAAAQEBAQEBAQEBAQEBAAAAAAAAAAAAAAAAAAAAAAAAAAABAQEBAQEBAQEBAQEAAAAAAAAAAAAAAAAAAAAAAAAAAAEBAQEBAQEBAQEBAQAAAAAAAAAAAAAAAAAAAAAAAAAAAQEBAQEBAQEBAQEBAAAAAAAAAAAAAAAAAAAAAAAAAAABAQEBAQEBAQEBAQEAAAAAAAAAAAAAAAAAAAAAAAAAAAEBAQEBAQEBAQEBAQAAAAAAAAAAAAAAAAAAAAAAAAAAAQEBAQEBAQEBAQEBAAAAAAAAAAAAAAAAAAAAAAAAAAABAQEBAQEBAQEBAQEAAAAAAAAAAAAAAAAAAAAAAAAAAAEBAQEBAQEBAQEBAQAAAAAAAAAAAAAAAAAAAQEBAQEBAQEBAQEBAQEBAQEBAAAAAAAAAAAAAAAAAAABAQEBAQEBAQEBAQEBAQEBAQEAAAAAAAAAAAAAAAAAAAEBAQEBAQEBAQEBAQEBAQEBAQAAAAAAAAAAAAAAAAAAAQEBAQEBAQEBAQEBAAAAAAAAAAAAAAAAAAAAAAAAAAABAQEBAQEBAQEBAQEAAAAAAAAAAAAAAAAAAAAAAAAAAAEBAQEBAQEBAQEBAQAAAAAAAAAAAAAAAAAAAQEBAQEBAQEBAQEBAQEBAQEBAAAAAAAAAAAAAAAAAAABAQEBAQEBAQEBAQEBAQEBAQEAAAAAAAAAAAAAAAAAAAEBAQEBAQEBAQEBAQEBAQEBAQAAAAAAAAAAAAAAAAAAAQEBAQEBAQEBAQEBAQEBAQEBAAAAAAAAAAAAAAAAAAABAQEBAQEBAQEBAQEBAQEBAQEAAAAAAAAAAAAAAAAAAAEBAQEBAQEBAQEBAQ==" - }, - "palette" : { - "originalArgb8888" : [ -265674 ], - "convertedRgb565" : [ -122 ] } }, "diagnostics" : [ ] @@ -60,14 +60,14 @@ "last_modified" : 1774359772406, "fingerprint" : "eeb7cc665386299403b7be1c272375d5077f3647c587f8033aa8c9275f840562", "metadata" : { + "palette" : { + "originalArgb8888" : [ -265674 ], + "convertedRgb565" : [ -122 ] + }, "tile" : { "width" : 32, "height" : 32, "paletteIndices" : "AQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAAAAAAAAAAABAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEAAAAAAAAAAAEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQAAAAAAAAAAAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAAAAAAAAAAABAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEAAAAAAAAAAAEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQAAAAAAAAAAAQEBAQEBAQEBAQEBAAAAAAAAAAAAAAAAAAAAAAAAAAABAQEBAQEBAQEBAQEAAAAAAAAAAAAAAAAAAAAAAAAAAAEBAQEBAQEBAQEBAQAAAAAAAAAAAAAAAAAAAAAAAAAAAQEBAQEBAQEBAQEBAAAAAAAAAAAAAAAAAAAAAAAAAAABAQEBAQEBAQEBAQEAAAAAAAAAAAAAAAAAAAAAAAAAAAEBAQEBAQEBAQEBAQAAAAAAAAAAAAAAAAAAAAAAAAAAAQEBAQEBAQEBAQEBAAAAAAAAAAAAAAAAAAAAAAAAAAABAQEBAQEBAQEBAQEAAAAAAAAAAAAAAAAAAAAAAAAAAAEBAQEBAQEBAQEBAQAAAAAAAAAAAAAAAAAAAQEBAQEBAQEBAQEBAQEBAQEBAAAAAAAAAAAAAAAAAAABAQEBAQEBAQEBAQEBAQEBAQEAAAAAAAAAAAAAAAAAAAEBAQEBAQEBAQEBAQEBAQEBAQAAAAAAAAAAAAAAAAAAAQEBAQEBAQEBAQEBAAAAAAAAAAAAAAAAAAAAAAAAAAABAQEBAQEBAQEBAQEAAAAAAAAAAAAAAAAAAAAAAAAAAAEBAQEBAQEBAQEBAQAAAAAAAAAAAAAAAAAAAQEBAQEBAQEBAQEBAQEBAQEBAAAAAAAAAAAAAAAAAAABAQEBAQEBAQEBAQEBAQEBAQEAAAAAAAAAAAAAAAAAAAEBAQEBAQEBAQEBAQEBAQEBAQAAAAAAAAAAAAAAAAAAAQEBAQEBAQEBAQEBAQEBAQEBAAAAAAAAAAAAAAAAAAABAQEBAQEBAQEBAQEBAQEBAQEAAAAAAAAAAAAAAAAAAAEBAQEBAQEBAQEBAQ==" - }, - "palette" : { - "originalArgb8888" : [ -265674 ], - "convertedRgb565" : [ -122 ] } }, "diagnostics" : [ ] @@ -78,14 +78,14 @@ "last_modified" : 1774359772408, "fingerprint" : "eeb7cc665386299403b7be1c272375d5077f3647c587f8033aa8c9275f840562", "metadata" : { + "palette" : { + "originalArgb8888" : [ -265674 ], + "convertedRgb565" : [ -122 ] + }, "tile" : { "width" : 32, "height" : 32, "paletteIndices" : "AQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAAAAAAAAAAABAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEAAAAAAAAAAAEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQAAAAAAAAAAAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAAAAAAAAAAABAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEAAAAAAAAAAAEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQAAAAAAAAAAAQEBAQEBAQEBAQEBAAAAAAAAAAAAAAAAAAAAAAAAAAABAQEBAQEBAQEBAQEAAAAAAAAAAAAAAAAAAAAAAAAAAAEBAQEBAQEBAQEBAQAAAAAAAAAAAAAAAAAAAAAAAAAAAQEBAQEBAQEBAQEBAAAAAAAAAAAAAAAAAAAAAAAAAAABAQEBAQEBAQEBAQEAAAAAAAAAAAAAAAAAAAAAAAAAAAEBAQEBAQEBAQEBAQAAAAAAAAAAAAAAAAAAAAAAAAAAAQEBAQEBAQEBAQEBAAAAAAAAAAAAAAAAAAAAAAAAAAABAQEBAQEBAQEBAQEAAAAAAAAAAAAAAAAAAAAAAAAAAAEBAQEBAQEBAQEBAQAAAAAAAAAAAAAAAAAAAQEBAQEBAQEBAQEBAQEBAQEBAAAAAAAAAAAAAAAAAAABAQEBAQEBAQEBAQEBAQEBAQEAAAAAAAAAAAAAAAAAAAEBAQEBAQEBAQEBAQEBAQEBAQAAAAAAAAAAAAAAAAAAAQEBAQEBAQEBAQEBAAAAAAAAAAAAAAAAAAAAAAAAAAABAQEBAQEBAQEBAQEAAAAAAAAAAAAAAAAAAAAAAAAAAAEBAQEBAQEBAQEBAQAAAAAAAAAAAAAAAAAAAQEBAQEBAQEBAQEBAQEBAQEBAAAAAAAAAAAAAAAAAAABAQEBAQEBAQEBAQEBAQEBAQEAAAAAAAAAAAAAAAAAAAEBAQEBAQEBAQEBAQEBAQEBAQAAAAAAAAAAAAAAAAAAAQEBAQEBAQEBAQEBAQEBAQEBAAAAAAAAAAAAAAAAAAABAQEBAQEBAQEBAQEBAQEBAQEAAAAAAAAAAAAAAAAAAAEBAQEBAQEBAQEBAQ==" - }, - "palette" : { - "originalArgb8888" : [ -265674 ], - "convertedRgb565" : [ -122 ] } }, "diagnostics" : [ ] @@ -96,14 +96,14 @@ "last_modified" : 1774359772409, "fingerprint" : "eeb7cc665386299403b7be1c272375d5077f3647c587f8033aa8c9275f840562", "metadata" : { + "palette" : { + "originalArgb8888" : [ -265674 ], + "convertedRgb565" : [ -122 ] + }, "tile" : { "width" : 32, "height" : 32, "paletteIndices" : "AQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAAAAAAAAAAABAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEAAAAAAAAAAAEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQAAAAAAAAAAAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAAAAAAAAAAABAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEAAAAAAAAAAAEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQAAAAAAAAAAAQEBAQEBAQEBAQEBAAAAAAAAAAAAAAAAAAAAAAAAAAABAQEBAQEBAQEBAQEAAAAAAAAAAAAAAAAAAAAAAAAAAAEBAQEBAQEBAQEBAQAAAAAAAAAAAAAAAAAAAAAAAAAAAQEBAQEBAQEBAQEBAAAAAAAAAAAAAAAAAAAAAAAAAAABAQEBAQEBAQEBAQEAAAAAAAAAAAAAAAAAAAAAAAAAAAEBAQEBAQEBAQEBAQAAAAAAAAAAAAAAAAAAAAAAAAAAAQEBAQEBAQEBAQEBAAAAAAAAAAAAAAAAAAAAAAAAAAABAQEBAQEBAQEBAQEAAAAAAAAAAAAAAAAAAAAAAAAAAAEBAQEBAQEBAQEBAQAAAAAAAAAAAAAAAAAAAQEBAQEBAQEBAQEBAQEBAQEBAAAAAAAAAAAAAAAAAAABAQEBAQEBAQEBAQEBAQEBAQEAAAAAAAAAAAAAAAAAAAEBAQEBAQEBAQEBAQEBAQEBAQAAAAAAAAAAAAAAAAAAAQEBAQEBAQEBAQEBAAAAAAAAAAAAAAAAAAAAAAAAAAABAQEBAQEBAQEBAQEAAAAAAAAAAAAAAAAAAAAAAAAAAAEBAQEBAQEBAQEBAQAAAAAAAAAAAAAAAAAAAQEBAQEBAQEBAQEBAQEBAQEBAAAAAAAAAAAAAAAAAAABAQEBAQEBAQEBAQEBAQEBAQEAAAAAAAAAAAAAAAAAAAEBAQEBAQEBAQEBAQEBAQEBAQAAAAAAAAAAAAAAAAAAAQEBAQEBAQEBAQEBAQEBAQEBAAAAAAAAAAAAAAAAAAABAQEBAQEBAQEBAQEBAQEBAQEAAAAAAAAAAAAAAAAAAAEBAQEBAQEBAQEBAQ==" - }, - "palette" : { - "originalArgb8888" : [ -265674 ], - "convertedRgb565" : [ -122 ] } }, "diagnostics" : [ ] @@ -114,14 +114,14 @@ "last_modified" : 1774359772411, "fingerprint" : "eeb7cc665386299403b7be1c272375d5077f3647c587f8033aa8c9275f840562", "metadata" : { + "palette" : { + "originalArgb8888" : [ -265674 ], + "convertedRgb565" : [ -122 ] + }, "tile" : { "width" : 32, "height" : 32, "paletteIndices" : "AQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAAAAAAAAAAABAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEAAAAAAAAAAAEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQAAAAAAAAAAAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAAAAAAAAAAABAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEAAAAAAAAAAAEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQAAAAAAAAAAAQEBAQEBAQEBAQEBAAAAAAAAAAAAAAAAAAAAAAAAAAABAQEBAQEBAQEBAQEAAAAAAAAAAAAAAAAAAAAAAAAAAAEBAQEBAQEBAQEBAQAAAAAAAAAAAAAAAAAAAAAAAAAAAQEBAQEBAQEBAQEBAAAAAAAAAAAAAAAAAAAAAAAAAAABAQEBAQEBAQEBAQEAAAAAAAAAAAAAAAAAAAAAAAAAAAEBAQEBAQEBAQEBAQAAAAAAAAAAAAAAAAAAAAAAAAAAAQEBAQEBAQEBAQEBAAAAAAAAAAAAAAAAAAAAAAAAAAABAQEBAQEBAQEBAQEAAAAAAAAAAAAAAAAAAAAAAAAAAAEBAQEBAQEBAQEBAQAAAAAAAAAAAAAAAAAAAQEBAQEBAQEBAQEBAQEBAQEBAAAAAAAAAAAAAAAAAAABAQEBAQEBAQEBAQEBAQEBAQEAAAAAAAAAAAAAAAAAAAEBAQEBAQEBAQEBAQEBAQEBAQAAAAAAAAAAAAAAAAAAAQEBAQEBAQEBAQEBAAAAAAAAAAAAAAAAAAAAAAAAAAABAQEBAQEBAQEBAQEAAAAAAAAAAAAAAAAAAAAAAAAAAAEBAQEBAQEBAQEBAQAAAAAAAAAAAAAAAAAAAQEBAQEBAQEBAQEBAQEBAQEBAAAAAAAAAAAAAAAAAAABAQEBAQEBAQEBAQEBAQEBAQEAAAAAAAAAAAAAAAAAAAEBAQEBAQEBAQEBAQEBAQEBAQAAAAAAAAAAAAAAAAAAAQEBAQEBAQEBAQEBAQEBAQEBAAAAAAAAAAAAAAAAAAABAQEBAQEBAQEBAQEBAQEBAQEAAAAAAAAAAAAAAAAAAAEBAQEBAQEBAQEBAQ==" - }, - "palette" : { - "originalArgb8888" : [ -265674 ], - "convertedRgb565" : [ -122 ] } }, "diagnostics" : [ ] @@ -132,14 +132,14 @@ "last_modified" : 1774359772412, "fingerprint" : "eeb7cc665386299403b7be1c272375d5077f3647c587f8033aa8c9275f840562", "metadata" : { + "palette" : { + "originalArgb8888" : [ -265674 ], + "convertedRgb565" : [ -122 ] + }, "tile" : { "width" : 32, "height" : 32, "paletteIndices" : "AQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAAAAAAAAAAABAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEAAAAAAAAAAAEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQAAAAAAAAAAAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAAAAAAAAAAABAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEAAAAAAAAAAAEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQAAAAAAAAAAAQEBAQEBAQEBAQEBAAAAAAAAAAAAAAAAAAAAAAAAAAABAQEBAQEBAQEBAQEAAAAAAAAAAAAAAAAAAAAAAAAAAAEBAQEBAQEBAQEBAQAAAAAAAAAAAAAAAAAAAAAAAAAAAQEBAQEBAQEBAQEBAAAAAAAAAAAAAAAAAAAAAAAAAAABAQEBAQEBAQEBAQEAAAAAAAAAAAAAAAAAAAAAAAAAAAEBAQEBAQEBAQEBAQAAAAAAAAAAAAAAAAAAAAAAAAAAAQEBAQEBAQEBAQEBAAAAAAAAAAAAAAAAAAAAAAAAAAABAQEBAQEBAQEBAQEAAAAAAAAAAAAAAAAAAAAAAAAAAAEBAQEBAQEBAQEBAQAAAAAAAAAAAAAAAAAAAQEBAQEBAQEBAQEBAQEBAQEBAAAAAAAAAAAAAAAAAAABAQEBAQEBAQEBAQEBAQEBAQEAAAAAAAAAAAAAAAAAAAEBAQEBAQEBAQEBAQEBAQEBAQAAAAAAAAAAAAAAAAAAAQEBAQEBAQEBAQEBAAAAAAAAAAAAAAAAAAAAAAAAAAABAQEBAQEBAQEBAQEAAAAAAAAAAAAAAAAAAAAAAAAAAAEBAQEBAQEBAQEBAQAAAAAAAAAAAAAAAAAAAQEBAQEBAQEBAQEBAQEBAQEBAAAAAAAAAAAAAAAAAAABAQEBAQEBAQEBAQEBAQEBAQEAAAAAAAAAAAAAAAAAAAEBAQEBAQEBAQEBAQEBAQEBAQAAAAAAAAAAAAAAAAAAAQEBAQEBAQEBAQEBAQEBAQEBAAAAAAAAAAAAAAAAAAABAQEBAQEBAQEBAQEBAQEBAQEAAAAAAAAAAAAAAAAAAAEBAQEBAQEBAQEBAQ==" - }, - "palette" : { - "originalArgb8888" : [ -265674 ], - "convertedRgb565" : [ -122 ] } }, "diagnostics" : [ ] @@ -150,14 +150,14 @@ "last_modified" : 1774359772413, "fingerprint" : "eeb7cc665386299403b7be1c272375d5077f3647c587f8033aa8c9275f840562", "metadata" : { + "palette" : { + "originalArgb8888" : [ -265674 ], + "convertedRgb565" : [ -122 ] + }, "tile" : { "width" : 32, "height" : 32, "paletteIndices" : "AQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAAAAAAAAAAABAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEAAAAAAAAAAAEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQAAAAAAAAAAAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAAAAAAAAAAABAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEAAAAAAAAAAAEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQAAAAAAAAAAAQEBAQEBAQEBAQEBAAAAAAAAAAAAAAAAAAAAAAAAAAABAQEBAQEBAQEBAQEAAAAAAAAAAAAAAAAAAAAAAAAAAAEBAQEBAQEBAQEBAQAAAAAAAAAAAAAAAAAAAAAAAAAAAQEBAQEBAQEBAQEBAAAAAAAAAAAAAAAAAAAAAAAAAAABAQEBAQEBAQEBAQEAAAAAAAAAAAAAAAAAAAAAAAAAAAEBAQEBAQEBAQEBAQAAAAAAAAAAAAAAAAAAAAAAAAAAAQEBAQEBAQEBAQEBAAAAAAAAAAAAAAAAAAAAAAAAAAABAQEBAQEBAQEBAQEAAAAAAAAAAAAAAAAAAAAAAAAAAAEBAQEBAQEBAQEBAQAAAAAAAAAAAAAAAAAAAQEBAQEBAQEBAQEBAQEBAQEBAAAAAAAAAAAAAAAAAAABAQEBAQEBAQEBAQEBAQEBAQEAAAAAAAAAAAAAAAAAAAEBAQEBAQEBAQEBAQEBAQEBAQAAAAAAAAAAAAAAAAAAAQEBAQEBAQEBAQEBAAAAAAAAAAAAAAAAAAAAAAAAAAABAQEBAQEBAQEBAQEAAAAAAAAAAAAAAAAAAAAAAAAAAAEBAQEBAQEBAQEBAQAAAAAAAAAAAAAAAAAAAQEBAQEBAQEBAQEBAQEBAQEBAAAAAAAAAAAAAAAAAAABAQEBAQEBAQEBAQEBAQEBAQEAAAAAAAAAAAAAAAAAAAEBAQEBAQEBAQEBAQEBAQEBAQAAAAAAAAAAAAAAAAAAAQEBAQEBAQEBAQEBAQEBAQEBAAAAAAAAAAAAAAAAAAABAQEBAQEBAQEBAQEBAQEBAQEAAAAAAAAAAAAAAAAAAAEBAQEBAQEBAQEBAQ==" - }, - "palette" : { - "originalArgb8888" : [ -265674 ], - "convertedRgb565" : [ -122 ] } }, "diagnostics" : [ ] @@ -168,14 +168,14 @@ "last_modified" : 1774359772415, "fingerprint" : "eeb7cc665386299403b7be1c272375d5077f3647c587f8033aa8c9275f840562", "metadata" : { + "palette" : { + "originalArgb8888" : [ -265674 ], + "convertedRgb565" : [ -122 ] + }, "tile" : { "width" : 32, "height" : 32, "paletteIndices" : "AQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAAAAAAAAAAABAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEAAAAAAAAAAAEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQAAAAAAAAAAAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAAAAAAAAAAABAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEAAAAAAAAAAAEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQAAAAAAAAAAAQEBAQEBAQEBAQEBAAAAAAAAAAAAAAAAAAAAAAAAAAABAQEBAQEBAQEBAQEAAAAAAAAAAAAAAAAAAAAAAAAAAAEBAQEBAQEBAQEBAQAAAAAAAAAAAAAAAAAAAAAAAAAAAQEBAQEBAQEBAQEBAAAAAAAAAAAAAAAAAAAAAAAAAAABAQEBAQEBAQEBAQEAAAAAAAAAAAAAAAAAAAAAAAAAAAEBAQEBAQEBAQEBAQAAAAAAAAAAAAAAAAAAAAAAAAAAAQEBAQEBAQEBAQEBAAAAAAAAAAAAAAAAAAAAAAAAAAABAQEBAQEBAQEBAQEAAAAAAAAAAAAAAAAAAAAAAAAAAAEBAQEBAQEBAQEBAQAAAAAAAAAAAAAAAAAAAQEBAQEBAQEBAQEBAQEBAQEBAAAAAAAAAAAAAAAAAAABAQEBAQEBAQEBAQEBAQEBAQEAAAAAAAAAAAAAAAAAAAEBAQEBAQEBAQEBAQEBAQEBAQAAAAAAAAAAAAAAAAAAAQEBAQEBAQEBAQEBAAAAAAAAAAAAAAAAAAAAAAAAAAABAQEBAQEBAQEBAQEAAAAAAAAAAAAAAAAAAAAAAAAAAAEBAQEBAQEBAQEBAQAAAAAAAAAAAAAAAAAAAQEBAQEBAQEBAQEBAQEBAQEBAAAAAAAAAAAAAAAAAAABAQEBAQEBAQEBAQEBAQEBAQEAAAAAAAAAAAAAAAAAAAEBAQEBAQEBAQEBAQEBAQEBAQAAAAAAAAAAAAAAAAAAAQEBAQEBAQEBAQEBAQEBAQEBAAAAAAAAAAAAAAAAAAABAQEBAQEBAQEBAQEBAQEBAQEAAAAAAAAAAAAAAAAAAAEBAQEBAQEBAQEBAQ==" - }, - "palette" : { - "originalArgb8888" : [ -265674 ], - "convertedRgb565" : [ -122 ] } }, "diagnostics" : [ ] @@ -186,14 +186,14 @@ "last_modified" : 1774359772416, "fingerprint" : "eeb7cc665386299403b7be1c272375d5077f3647c587f8033aa8c9275f840562", "metadata" : { + "palette" : { + "originalArgb8888" : [ -265674 ], + "convertedRgb565" : [ -122 ] + }, "tile" : { "width" : 32, "height" : 32, "paletteIndices" : "AQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAAAAAAAAAAABAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEAAAAAAAAAAAEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQAAAAAAAAAAAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAAAAAAAAAAABAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEAAAAAAAAAAAEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQAAAAAAAAAAAQEBAQEBAQEBAQEBAAAAAAAAAAAAAAAAAAAAAAAAAAABAQEBAQEBAQEBAQEAAAAAAAAAAAAAAAAAAAAAAAAAAAEBAQEBAQEBAQEBAQAAAAAAAAAAAAAAAAAAAAAAAAAAAQEBAQEBAQEBAQEBAAAAAAAAAAAAAAAAAAAAAAAAAAABAQEBAQEBAQEBAQEAAAAAAAAAAAAAAAAAAAAAAAAAAAEBAQEBAQEBAQEBAQAAAAAAAAAAAAAAAAAAAAAAAAAAAQEBAQEBAQEBAQEBAAAAAAAAAAAAAAAAAAAAAAAAAAABAQEBAQEBAQEBAQEAAAAAAAAAAAAAAAAAAAAAAAAAAAEBAQEBAQEBAQEBAQAAAAAAAAAAAAAAAAAAAQEBAQEBAQEBAQEBAQEBAQEBAAAAAAAAAAAAAAAAAAABAQEBAQEBAQEBAQEBAQEBAQEAAAAAAAAAAAAAAAAAAAEBAQEBAQEBAQEBAQEBAQEBAQAAAAAAAAAAAAAAAAAAAQEBAQEBAQEBAQEBAAAAAAAAAAAAAAAAAAAAAAAAAAABAQEBAQEBAQEBAQEAAAAAAAAAAAAAAAAAAAAAAAAAAAEBAQEBAQEBAQEBAQAAAAAAAAAAAAAAAAAAAQEBAQEBAQEBAQEBAQEBAQEBAAAAAAAAAAAAAAAAAAABAQEBAQEBAQEBAQEBAQEBAQEAAAAAAAAAAAAAAAAAAAEBAQEBAQEBAQEBAQEBAQEBAQAAAAAAAAAAAAAAAAAAAQEBAQEBAQEBAQEBAQEBAQEBAAAAAAAAAAAAAAAAAAABAQEBAQEBAQEBAQEBAQEBAQEAAAAAAAAAAAAAAAAAAAEBAQEBAQEBAQEBAQ==" - }, - "palette" : { - "originalArgb8888" : [ -265674 ], - "convertedRgb565" : [ -122 ] } }, "diagnostics" : [ ] @@ -204,14 +204,14 @@ "last_modified" : 1774359772417, "fingerprint" : "eeb7cc665386299403b7be1c272375d5077f3647c587f8033aa8c9275f840562", "metadata" : { + "palette" : { + "originalArgb8888" : [ -265674 ], + "convertedRgb565" : [ -122 ] + }, "tile" : { "width" : 32, "height" : 32, "paletteIndices" : "AQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAAAAAAAAAAABAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEAAAAAAAAAAAEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQAAAAAAAAAAAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAAAAAAAAAAABAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEAAAAAAAAAAAEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQAAAAAAAAAAAQEBAQEBAQEBAQEBAAAAAAAAAAAAAAAAAAAAAAAAAAABAQEBAQEBAQEBAQEAAAAAAAAAAAAAAAAAAAAAAAAAAAEBAQEBAQEBAQEBAQAAAAAAAAAAAAAAAAAAAAAAAAAAAQEBAQEBAQEBAQEBAAAAAAAAAAAAAAAAAAAAAAAAAAABAQEBAQEBAQEBAQEAAAAAAAAAAAAAAAAAAAAAAAAAAAEBAQEBAQEBAQEBAQAAAAAAAAAAAAAAAAAAAAAAAAAAAQEBAQEBAQEBAQEBAAAAAAAAAAAAAAAAAAAAAAAAAAABAQEBAQEBAQEBAQEAAAAAAAAAAAAAAAAAAAAAAAAAAAEBAQEBAQEBAQEBAQAAAAAAAAAAAAAAAAAAAQEBAQEBAQEBAQEBAQEBAQEBAAAAAAAAAAAAAAAAAAABAQEBAQEBAQEBAQEBAQEBAQEAAAAAAAAAAAAAAAAAAAEBAQEBAQEBAQEBAQEBAQEBAQAAAAAAAAAAAAAAAAAAAQEBAQEBAQEBAQEBAAAAAAAAAAAAAAAAAAAAAAAAAAABAQEBAQEBAQEBAQEAAAAAAAAAAAAAAAAAAAAAAAAAAAEBAQEBAQEBAQEBAQAAAAAAAAAAAAAAAAAAAQEBAQEBAQEBAQEBAQEBAQEBAAAAAAAAAAAAAAAAAAABAQEBAQEBAQEBAQEBAQEBAQEAAAAAAAAAAAAAAAAAAAEBAQEBAQEBAQEBAQEBAQEBAQAAAAAAAAAAAAAAAAAAAQEBAQEBAQEBAQEBAQEBAQEBAAAAAAAAAAAAAAAAAAABAQEBAQEBAQEBAQEBAQEBAQEAAAAAAAAAAAAAAAAAAAEBAQEBAQEBAQEBAQ==" - }, - "palette" : { - "originalArgb8888" : [ -265674 ], - "convertedRgb565" : [ -122 ] } }, "diagnostics" : [ ] @@ -222,14 +222,14 @@ "last_modified" : 1774359772418, "fingerprint" : "eeb7cc665386299403b7be1c272375d5077f3647c587f8033aa8c9275f840562", "metadata" : { + "palette" : { + "originalArgb8888" : [ -265674 ], + "convertedRgb565" : [ -122 ] + }, "tile" : { "width" : 32, "height" : 32, "paletteIndices" : "AQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAAAAAAAAAAABAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEAAAAAAAAAAAEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQAAAAAAAAAAAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAAAAAAAAAAABAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEAAAAAAAAAAAEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQAAAAAAAAAAAQEBAQEBAQEBAQEBAAAAAAAAAAAAAAAAAAAAAAAAAAABAQEBAQEBAQEBAQEAAAAAAAAAAAAAAAAAAAAAAAAAAAEBAQEBAQEBAQEBAQAAAAAAAAAAAAAAAAAAAAAAAAAAAQEBAQEBAQEBAQEBAAAAAAAAAAAAAAAAAAAAAAAAAAABAQEBAQEBAQEBAQEAAAAAAAAAAAAAAAAAAAAAAAAAAAEBAQEBAQEBAQEBAQAAAAAAAAAAAAAAAAAAAAAAAAAAAQEBAQEBAQEBAQEBAAAAAAAAAAAAAAAAAAAAAAAAAAABAQEBAQEBAQEBAQEAAAAAAAAAAAAAAAAAAAAAAAAAAAEBAQEBAQEBAQEBAQAAAAAAAAAAAAAAAAAAAQEBAQEBAQEBAQEBAQEBAQEBAAAAAAAAAAAAAAAAAAABAQEBAQEBAQEBAQEBAQEBAQEAAAAAAAAAAAAAAAAAAAEBAQEBAQEBAQEBAQEBAQEBAQAAAAAAAAAAAAAAAAAAAQEBAQEBAQEBAQEBAAAAAAAAAAAAAAAAAAAAAAAAAAABAQEBAQEBAQEBAQEAAAAAAAAAAAAAAAAAAAAAAAAAAAEBAQEBAQEBAQEBAQAAAAAAAAAAAAAAAAAAAQEBAQEBAQEBAQEBAQEBAQEBAAAAAAAAAAAAAAAAAAABAQEBAQEBAQEBAQEBAQEBAQEAAAAAAAAAAAAAAAAAAAEBAQEBAQEBAQEBAQEBAQEBAQAAAAAAAAAAAAAAAAAAAQEBAQEBAQEBAQEBAQEBAQEBAAAAAAAAAAAAAAAAAAABAQEBAQEBAQEBAQEBAQEBAQEAAAAAAAAAAAAAAAAAAAEBAQEBAQEBAQEBAQ==" - }, - "palette" : { - "originalArgb8888" : [ -265674 ], - "convertedRgb565" : [ -122 ] } }, "diagnostics" : [ ] @@ -240,14 +240,14 @@ "last_modified" : 1774359772420, "fingerprint" : "eeb7cc665386299403b7be1c272375d5077f3647c587f8033aa8c9275f840562", "metadata" : { + "palette" : { + "originalArgb8888" : [ -265674 ], + "convertedRgb565" : [ -122 ] + }, "tile" : { "width" : 32, "height" : 32, "paletteIndices" : "AQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAAAAAAAAAAABAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEAAAAAAAAAAAEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQAAAAAAAAAAAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAAAAAAAAAAABAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEAAAAAAAAAAAEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQAAAAAAAAAAAQEBAQEBAQEBAQEBAAAAAAAAAAAAAAAAAAAAAAAAAAABAQEBAQEBAQEBAQEAAAAAAAAAAAAAAAAAAAAAAAAAAAEBAQEBAQEBAQEBAQAAAAAAAAAAAAAAAAAAAAAAAAAAAQEBAQEBAQEBAQEBAAAAAAAAAAAAAAAAAAAAAAAAAAABAQEBAQEBAQEBAQEAAAAAAAAAAAAAAAAAAAAAAAAAAAEBAQEBAQEBAQEBAQAAAAAAAAAAAAAAAAAAAAAAAAAAAQEBAQEBAQEBAQEBAAAAAAAAAAAAAAAAAAAAAAAAAAABAQEBAQEBAQEBAQEAAAAAAAAAAAAAAAAAAAAAAAAAAAEBAQEBAQEBAQEBAQAAAAAAAAAAAAAAAAAAAQEBAQEBAQEBAQEBAQEBAQEBAAAAAAAAAAAAAAAAAAABAQEBAQEBAQEBAQEBAQEBAQEAAAAAAAAAAAAAAAAAAAEBAQEBAQEBAQEBAQEBAQEBAQAAAAAAAAAAAAAAAAAAAQEBAQEBAQEBAQEBAAAAAAAAAAAAAAAAAAAAAAAAAAABAQEBAQEBAQEBAQEAAAAAAAAAAAAAAAAAAAAAAAAAAAEBAQEBAQEBAQEBAQAAAAAAAAAAAAAAAAAAAQEBAQEBAQEBAQEBAQEBAQEBAAAAAAAAAAAAAAAAAAABAQEBAQEBAQEBAQEBAQEBAQEAAAAAAAAAAAAAAAAAAAEBAQEBAQEBAQEBAQEBAQEBAQAAAAAAAAAAAAAAAAAAAQEBAQEBAQEBAQEBAQEBAQEBAAAAAAAAAAAAAAAAAAABAQEBAQEBAQEBAQEBAQEBAQEAAAAAAAAAAAAAAAAAAAEBAQEBAQEBAQEBAQ==" - }, - "palette" : { - "originalArgb8888" : [ -265674 ], - "convertedRgb565" : [ -122 ] } }, "diagnostics" : [ ] @@ -258,14 +258,14 @@ "last_modified" : 1774359772421, "fingerprint" : "eeb7cc665386299403b7be1c272375d5077f3647c587f8033aa8c9275f840562", "metadata" : { + "palette" : { + "originalArgb8888" : [ -265674 ], + "convertedRgb565" : [ -122 ] + }, "tile" : { "width" : 32, "height" : 32, "paletteIndices" : "AQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAAAAAAAAAAABAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEAAAAAAAAAAAEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQAAAAAAAAAAAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAAAAAAAAAAABAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEAAAAAAAAAAAEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQAAAAAAAAAAAQEBAQEBAQEBAQEBAAAAAAAAAAAAAAAAAAAAAAAAAAABAQEBAQEBAQEBAQEAAAAAAAAAAAAAAAAAAAAAAAAAAAEBAQEBAQEBAQEBAQAAAAAAAAAAAAAAAAAAAAAAAAAAAQEBAQEBAQEBAQEBAAAAAAAAAAAAAAAAAAAAAAAAAAABAQEBAQEBAQEBAQEAAAAAAAAAAAAAAAAAAAAAAAAAAAEBAQEBAQEBAQEBAQAAAAAAAAAAAAAAAAAAAAAAAAAAAQEBAQEBAQEBAQEBAAAAAAAAAAAAAAAAAAAAAAAAAAABAQEBAQEBAQEBAQEAAAAAAAAAAAAAAAAAAAAAAAAAAAEBAQEBAQEBAQEBAQAAAAAAAAAAAAAAAAAAAQEBAQEBAQEBAQEBAQEBAQEBAAAAAAAAAAAAAAAAAAABAQEBAQEBAQEBAQEBAQEBAQEAAAAAAAAAAAAAAAAAAAEBAQEBAQEBAQEBAQEBAQEBAQAAAAAAAAAAAAAAAAAAAQEBAQEBAQEBAQEBAAAAAAAAAAAAAAAAAAAAAAAAAAABAQEBAQEBAQEBAQEAAAAAAAAAAAAAAAAAAAAAAAAAAAEBAQEBAQEBAQEBAQAAAAAAAAAAAAAAAAAAAQEBAQEBAQEBAQEBAQEBAQEBAAAAAAAAAAAAAAAAAAABAQEBAQEBAQEBAQEBAQEBAQEAAAAAAAAAAAAAAAAAAAEBAQEBAQEBAQEBAQEBAQEBAQAAAAAAAAAAAAAAAAAAAQEBAQEBAQEBAQEBAQEBAQEBAAAAAAAAAAAAAAAAAAABAQEBAQEBAQEBAQEBAQEBAQEAAAAAAAAAAAAAAAAAAAEBAQEBAQEBAQEBAQ==" - }, - "palette" : { - "originalArgb8888" : [ -265674 ], - "convertedRgb565" : [ -122 ] } }, "diagnostics" : [ ] @@ -276,14 +276,14 @@ "last_modified" : 1774359772423, "fingerprint" : "eeb7cc665386299403b7be1c272375d5077f3647c587f8033aa8c9275f840562", "metadata" : { + "palette" : { + "originalArgb8888" : [ -265674 ], + "convertedRgb565" : [ -122 ] + }, "tile" : { "width" : 32, "height" : 32, "paletteIndices" : "AQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAAAAAAAAAAABAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEAAAAAAAAAAAEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQAAAAAAAAAAAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAAAAAAAAAAABAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEAAAAAAAAAAAEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQAAAAAAAAAAAQEBAQEBAQEBAQEBAAAAAAAAAAAAAAAAAAAAAAAAAAABAQEBAQEBAQEBAQEAAAAAAAAAAAAAAAAAAAAAAAAAAAEBAQEBAQEBAQEBAQAAAAAAAAAAAAAAAAAAAAAAAAAAAQEBAQEBAQEBAQEBAAAAAAAAAAAAAAAAAAAAAAAAAAABAQEBAQEBAQEBAQEAAAAAAAAAAAAAAAAAAAAAAAAAAAEBAQEBAQEBAQEBAQAAAAAAAAAAAAAAAAAAAAAAAAAAAQEBAQEBAQEBAQEBAAAAAAAAAAAAAAAAAAAAAAAAAAABAQEBAQEBAQEBAQEAAAAAAAAAAAAAAAAAAAAAAAAAAAEBAQEBAQEBAQEBAQAAAAAAAAAAAAAAAAAAAQEBAQEBAQEBAQEBAQEBAQEBAAAAAAAAAAAAAAAAAAABAQEBAQEBAQEBAQEBAQEBAQEAAAAAAAAAAAAAAAAAAAEBAQEBAQEBAQEBAQEBAQEBAQAAAAAAAAAAAAAAAAAAAQEBAQEBAQEBAQEBAAAAAAAAAAAAAAAAAAAAAAAAAAABAQEBAQEBAQEBAQEAAAAAAAAAAAAAAAAAAAAAAAAAAAEBAQEBAQEBAQEBAQAAAAAAAAAAAAAAAAAAAQEBAQEBAQEBAQEBAQEBAQEBAAAAAAAAAAAAAAAAAAABAQEBAQEBAQEBAQEBAQEBAQEAAAAAAAAAAAAAAAAAAAEBAQEBAQEBAQEBAQEBAQEBAQAAAAAAAAAAAAAAAAAAAQEBAQEBAQEBAQEBAQEBAQEBAAAAAAAAAAAAAAAAAAABAQEBAQEBAQEBAQEBAQEBAQEAAAAAAAAAAAAAAAAAAAEBAQEBAQEBAQEBAQ==" - }, - "palette" : { - "originalArgb8888" : [ -265674 ], - "convertedRgb565" : [ -122 ] } }, "diagnostics" : [ ] @@ -294,14 +294,14 @@ "last_modified" : 1774359772424, "fingerprint" : "eeb7cc665386299403b7be1c272375d5077f3647c587f8033aa8c9275f840562", "metadata" : { + "palette" : { + "originalArgb8888" : [ -265674 ], + "convertedRgb565" : [ -122 ] + }, "tile" : { "width" : 32, "height" : 32, "paletteIndices" : "AQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAAAAAAAAAAABAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEAAAAAAAAAAAEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQAAAAAAAAAAAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAAAAAAAAAAABAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEAAAAAAAAAAAEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQAAAAAAAAAAAQEBAQEBAQEBAQEBAAAAAAAAAAAAAAAAAAAAAAAAAAABAQEBAQEBAQEBAQEAAAAAAAAAAAAAAAAAAAAAAAAAAAEBAQEBAQEBAQEBAQAAAAAAAAAAAAAAAAAAAAAAAAAAAQEBAQEBAQEBAQEBAAAAAAAAAAAAAAAAAAAAAAAAAAABAQEBAQEBAQEBAQEAAAAAAAAAAAAAAAAAAAAAAAAAAAEBAQEBAQEBAQEBAQAAAAAAAAAAAAAAAAAAAAAAAAAAAQEBAQEBAQEBAQEBAAAAAAAAAAAAAAAAAAAAAAAAAAABAQEBAQEBAQEBAQEAAAAAAAAAAAAAAAAAAAAAAAAAAAEBAQEBAQEBAQEBAQAAAAAAAAAAAAAAAAAAAQEBAQEBAQEBAQEBAQEBAQEBAAAAAAAAAAAAAAAAAAABAQEBAQEBAQEBAQEBAQEBAQEAAAAAAAAAAAAAAAAAAAEBAQEBAQEBAQEBAQEBAQEBAQAAAAAAAAAAAAAAAAAAAQEBAQEBAQEBAQEBAAAAAAAAAAAAAAAAAAAAAAAAAAABAQEBAQEBAQEBAQEAAAAAAAAAAAAAAAAAAAAAAAAAAAEBAQEBAQEBAQEBAQAAAAAAAAAAAAAAAAAAAQEBAQEBAQEBAQEBAQEBAQEBAAAAAAAAAAAAAAAAAAABAQEBAQEBAQEBAQEBAQEBAQEAAAAAAAAAAAAAAAAAAAEBAQEBAQEBAQEBAQEBAQEBAQAAAAAAAAAAAAAAAAAAAQEBAQEBAQEBAQEBAQEBAQEBAAAAAAAAAAAAAAAAAAABAQEBAQEBAQEBAQEBAQEBAQEAAAAAAAAAAAAAAAAAAAEBAQEBAQEBAQEBAQ==" - }, - "palette" : { - "originalArgb8888" : [ -265674 ], - "convertedRgb565" : [ -122 ] } }, "diagnostics" : [ ] @@ -312,14 +312,14 @@ "last_modified" : 1774359772425, "fingerprint" : "eeb7cc665386299403b7be1c272375d5077f3647c587f8033aa8c9275f840562", "metadata" : { + "palette" : { + "originalArgb8888" : [ -265674 ], + "convertedRgb565" : [ -122 ] + }, "tile" : { "width" : 32, "height" : 32, "paletteIndices" : "AQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAAAAAAAAAAABAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEAAAAAAAAAAAEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQAAAAAAAAAAAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAAAAAAAAAAABAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEAAAAAAAAAAAEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQAAAAAAAAAAAQEBAQEBAQEBAQEBAAAAAAAAAAAAAAAAAAAAAAAAAAABAQEBAQEBAQEBAQEAAAAAAAAAAAAAAAAAAAAAAAAAAAEBAQEBAQEBAQEBAQAAAAAAAAAAAAAAAAAAAAAAAAAAAQEBAQEBAQEBAQEBAAAAAAAAAAAAAAAAAAAAAAAAAAABAQEBAQEBAQEBAQEAAAAAAAAAAAAAAAAAAAAAAAAAAAEBAQEBAQEBAQEBAQAAAAAAAAAAAAAAAAAAAAAAAAAAAQEBAQEBAQEBAQEBAAAAAAAAAAAAAAAAAAAAAAAAAAABAQEBAQEBAQEBAQEAAAAAAAAAAAAAAAAAAAAAAAAAAAEBAQEBAQEBAQEBAQAAAAAAAAAAAAAAAAAAAQEBAQEBAQEBAQEBAQEBAQEBAAAAAAAAAAAAAAAAAAABAQEBAQEBAQEBAQEBAQEBAQEAAAAAAAAAAAAAAAAAAAEBAQEBAQEBAQEBAQEBAQEBAQAAAAAAAAAAAAAAAAAAAQEBAQEBAQEBAQEBAAAAAAAAAAAAAAAAAAAAAAAAAAABAQEBAQEBAQEBAQEAAAAAAAAAAAAAAAAAAAAAAAAAAAEBAQEBAQEBAQEBAQAAAAAAAAAAAAAAAAAAAQEBAQEBAQEBAQEBAQEBAQEBAAAAAAAAAAAAAAAAAAABAQEBAQEBAQEBAQEBAQEBAQEAAAAAAAAAAAAAAAAAAAEBAQEBAQEBAQEBAQEBAQEBAQAAAAAAAAAAAAAAAAAAAQEBAQEBAQEBAQEBAQEBAQEBAAAAAAAAAAAAAAAAAAABAQEBAQEBAQEBAQEBAQEBAQEAAAAAAAAAAAAAAAAAAAEBAQEBAQEBAQEBAQ==" - }, - "palette" : { - "originalArgb8888" : [ -265674 ], - "convertedRgb565" : [ -122 ] } }, "diagnostics" : [ ] @@ -330,14 +330,14 @@ "last_modified" : 1774359772426, "fingerprint" : "eeb7cc665386299403b7be1c272375d5077f3647c587f8033aa8c9275f840562", "metadata" : { + "palette" : { + "originalArgb8888" : [ -265674 ], + "convertedRgb565" : [ -122 ] + }, "tile" : { "width" : 32, "height" : 32, "paletteIndices" : "AQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAAAAAAAAAAABAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEAAAAAAAAAAAEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQAAAAAAAAAAAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAAAAAAAAAAABAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEAAAAAAAAAAAEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQAAAAAAAAAAAQEBAQEBAQEBAQEBAAAAAAAAAAAAAAAAAAAAAAAAAAABAQEBAQEBAQEBAQEAAAAAAAAAAAAAAAAAAAAAAAAAAAEBAQEBAQEBAQEBAQAAAAAAAAAAAAAAAAAAAAAAAAAAAQEBAQEBAQEBAQEBAAAAAAAAAAAAAAAAAAAAAAAAAAABAQEBAQEBAQEBAQEAAAAAAAAAAAAAAAAAAAAAAAAAAAEBAQEBAQEBAQEBAQAAAAAAAAAAAAAAAAAAAAAAAAAAAQEBAQEBAQEBAQEBAAAAAAAAAAAAAAAAAAAAAAAAAAABAQEBAQEBAQEBAQEAAAAAAAAAAAAAAAAAAAAAAAAAAAEBAQEBAQEBAQEBAQAAAAAAAAAAAAAAAAAAAQEBAQEBAQEBAQEBAQEBAQEBAAAAAAAAAAAAAAAAAAABAQEBAQEBAQEBAQEBAQEBAQEAAAAAAAAAAAAAAAAAAAEBAQEBAQEBAQEBAQEBAQEBAQAAAAAAAAAAAAAAAAAAAQEBAQEBAQEBAQEBAAAAAAAAAAAAAAAAAAAAAAAAAAABAQEBAQEBAQEBAQEAAAAAAAAAAAAAAAAAAAAAAAAAAAEBAQEBAQEBAQEBAQAAAAAAAAAAAAAAAAAAAQEBAQEBAQEBAQEBAQEBAQEBAAAAAAAAAAAAAAAAAAABAQEBAQEBAQEBAQEBAQEBAQEAAAAAAAAAAAAAAAAAAAEBAQEBAQEBAQEBAQEBAQEBAQAAAAAAAAAAAAAAAAAAAQEBAQEBAQEBAQEBAQEBAQEBAAAAAAAAAAAAAAAAAAABAQEBAQEBAQEBAQEBAQEBAQEAAAAAAAAAAAAAAAAAAAEBAQEBAQEBAQEBAQ==" - }, - "palette" : { - "originalArgb8888" : [ -265674 ], - "convertedRgb565" : [ -122 ] } }, "diagnostics" : [ ] @@ -348,14 +348,14 @@ "last_modified" : 1774359772428, "fingerprint" : "eeb7cc665386299403b7be1c272375d5077f3647c587f8033aa8c9275f840562", "metadata" : { + "palette" : { + "originalArgb8888" : [ -265674 ], + "convertedRgb565" : [ -122 ] + }, "tile" : { "width" : 32, "height" : 32, "paletteIndices" : "AQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAAAAAAAAAAABAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEAAAAAAAAAAAEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQAAAAAAAAAAAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAAAAAAAAAAABAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEAAAAAAAAAAAEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQAAAAAAAAAAAQEBAQEBAQEBAQEBAAAAAAAAAAAAAAAAAAAAAAAAAAABAQEBAQEBAQEBAQEAAAAAAAAAAAAAAAAAAAAAAAAAAAEBAQEBAQEBAQEBAQAAAAAAAAAAAAAAAAAAAAAAAAAAAQEBAQEBAQEBAQEBAAAAAAAAAAAAAAAAAAAAAAAAAAABAQEBAQEBAQEBAQEAAAAAAAAAAAAAAAAAAAAAAAAAAAEBAQEBAQEBAQEBAQAAAAAAAAAAAAAAAAAAAAAAAAAAAQEBAQEBAQEBAQEBAAAAAAAAAAAAAAAAAAAAAAAAAAABAQEBAQEBAQEBAQEAAAAAAAAAAAAAAAAAAAAAAAAAAAEBAQEBAQEBAQEBAQAAAAAAAAAAAAAAAAAAAQEBAQEBAQEBAQEBAQEBAQEBAAAAAAAAAAAAAAAAAAABAQEBAQEBAQEBAQEBAQEBAQEAAAAAAAAAAAAAAAAAAAEBAQEBAQEBAQEBAQEBAQEBAQAAAAAAAAAAAAAAAAAAAQEBAQEBAQEBAQEBAAAAAAAAAAAAAAAAAAAAAAAAAAABAQEBAQEBAQEBAQEAAAAAAAAAAAAAAAAAAAAAAAAAAAEBAQEBAQEBAQEBAQAAAAAAAAAAAAAAAAAAAQEBAQEBAQEBAQEBAQEBAQEBAAAAAAAAAAAAAAAAAAABAQEBAQEBAQEBAQEBAQEBAQEAAAAAAAAAAAAAAAAAAAEBAQEBAQEBAQEBAQEBAQEBAQAAAAAAAAAAAAAAAAAAAQEBAQEBAQEBAQEBAQEBAQEBAAAAAAAAAAAAAAAAAAABAQEBAQEBAQEBAQEBAQEBAQEAAAAAAAAAAAAAAAAAAAEBAQEBAQEBAQEBAQ==" - }, - "palette" : { - "originalArgb8888" : [ -265674 ], - "convertedRgb565" : [ -122 ] } }, "diagnostics" : [ ] @@ -366,14 +366,14 @@ "last_modified" : 1774359772429, "fingerprint" : "eeb7cc665386299403b7be1c272375d5077f3647c587f8033aa8c9275f840562", "metadata" : { + "palette" : { + "originalArgb8888" : [ -265674 ], + "convertedRgb565" : [ -122 ] + }, "tile" : { "width" : 32, "height" : 32, "paletteIndices" : "AQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAAAAAAAAAAABAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEAAAAAAAAAAAEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQAAAAAAAAAAAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAAAAAAAAAAABAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEAAAAAAAAAAAEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQAAAAAAAAAAAQEBAQEBAQEBAQEBAAAAAAAAAAAAAAAAAAAAAAAAAAABAQEBAQEBAQEBAQEAAAAAAAAAAAAAAAAAAAAAAAAAAAEBAQEBAQEBAQEBAQAAAAAAAAAAAAAAAAAAAAAAAAAAAQEBAQEBAQEBAQEBAAAAAAAAAAAAAAAAAAAAAAAAAAABAQEBAQEBAQEBAQEAAAAAAAAAAAAAAAAAAAAAAAAAAAEBAQEBAQEBAQEBAQAAAAAAAAAAAAAAAAAAAAAAAAAAAQEBAQEBAQEBAQEBAAAAAAAAAAAAAAAAAAAAAAAAAAABAQEBAQEBAQEBAQEAAAAAAAAAAAAAAAAAAAAAAAAAAAEBAQEBAQEBAQEBAQAAAAAAAAAAAAAAAAAAAQEBAQEBAQEBAQEBAQEBAQEBAAAAAAAAAAAAAAAAAAABAQEBAQEBAQEBAQEBAQEBAQEAAAAAAAAAAAAAAAAAAAEBAQEBAQEBAQEBAQEBAQEBAQAAAAAAAAAAAAAAAAAAAQEBAQEBAQEBAQEBAAAAAAAAAAAAAAAAAAAAAAAAAAABAQEBAQEBAQEBAQEAAAAAAAAAAAAAAAAAAAAAAAAAAAEBAQEBAQEBAQEBAQAAAAAAAAAAAAAAAAAAAQEBAQEBAQEBAQEBAQEBAQEBAAAAAAAAAAAAAAAAAAABAQEBAQEBAQEBAQEBAQEBAQEAAAAAAAAAAAAAAAAAAAEBAQEBAQEBAQEBAQEBAQEBAQAAAAAAAAAAAAAAAAAAAQEBAQEBAQEBAQEBAQEBAQEBAAAAAAAAAAAAAAAAAAABAQEBAQEBAQEBAQEBAQEBAQEAAAAAAAAAAAAAAAAAAAEBAQEBAQEBAQEBAQ==" - }, - "palette" : { - "originalArgb8888" : [ -265674 ], - "convertedRgb565" : [ -122 ] } }, "diagnostics" : [ ] @@ -384,14 +384,14 @@ "last_modified" : 1774359772430, "fingerprint" : "eeb7cc665386299403b7be1c272375d5077f3647c587f8033aa8c9275f840562", "metadata" : { + "palette" : { + "originalArgb8888" : [ -265674 ], + "convertedRgb565" : [ -122 ] + }, "tile" : { "width" : 32, "height" : 32, "paletteIndices" : "AQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAAAAAAAAAAABAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEAAAAAAAAAAAEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQAAAAAAAAAAAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAAAAAAAAAAABAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEAAAAAAAAAAAEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQAAAAAAAAAAAQEBAQEBAQEBAQEBAAAAAAAAAAAAAAAAAAAAAAAAAAABAQEBAQEBAQEBAQEAAAAAAAAAAAAAAAAAAAAAAAAAAAEBAQEBAQEBAQEBAQAAAAAAAAAAAAAAAAAAAAAAAAAAAQEBAQEBAQEBAQEBAAAAAAAAAAAAAAAAAAAAAAAAAAABAQEBAQEBAQEBAQEAAAAAAAAAAAAAAAAAAAAAAAAAAAEBAQEBAQEBAQEBAQAAAAAAAAAAAAAAAAAAAAAAAAAAAQEBAQEBAQEBAQEBAAAAAAAAAAAAAAAAAAAAAAAAAAABAQEBAQEBAQEBAQEAAAAAAAAAAAAAAAAAAAAAAAAAAAEBAQEBAQEBAQEBAQAAAAAAAAAAAAAAAAAAAQEBAQEBAQEBAQEBAQEBAQEBAAAAAAAAAAAAAAAAAAABAQEBAQEBAQEBAQEBAQEBAQEAAAAAAAAAAAAAAAAAAAEBAQEBAQEBAQEBAQEBAQEBAQAAAAAAAAAAAAAAAAAAAQEBAQEBAQEBAQEBAAAAAAAAAAAAAAAAAAAAAAAAAAABAQEBAQEBAQEBAQEAAAAAAAAAAAAAAAAAAAAAAAAAAAEBAQEBAQEBAQEBAQAAAAAAAAAAAAAAAAAAAQEBAQEBAQEBAQEBAQEBAQEBAAAAAAAAAAAAAAAAAAABAQEBAQEBAQEBAQEBAQEBAQEAAAAAAAAAAAAAAAAAAAEBAQEBAQEBAQEBAQEBAQEBAQAAAAAAAAAAAAAAAAAAAQEBAQEBAQEBAQEBAQEBAQEBAAAAAAAAAAAAAAAAAAABAQEBAQEBAQEBAQEBAQEBAQEAAAAAAAAAAAAAAAAAAAEBAQEBAQEBAQEBAQ==" - }, - "palette" : { - "originalArgb8888" : [ -265674 ], - "convertedRgb565" : [ -122 ] } }, "diagnostics" : [ ] @@ -402,14 +402,14 @@ "last_modified" : 1774359772431, "fingerprint" : "eeb7cc665386299403b7be1c272375d5077f3647c587f8033aa8c9275f840562", "metadata" : { + "palette" : { + "originalArgb8888" : [ -265674 ], + "convertedRgb565" : [ -122 ] + }, "tile" : { "width" : 32, "height" : 32, "paletteIndices" : "AQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAAAAAAAAAAABAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEAAAAAAAAAAAEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQAAAAAAAAAAAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAAAAAAAAAAABAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEAAAAAAAAAAAEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQAAAAAAAAAAAQEBAQEBAQEBAQEBAAAAAAAAAAAAAAAAAAAAAAAAAAABAQEBAQEBAQEBAQEAAAAAAAAAAAAAAAAAAAAAAAAAAAEBAQEBAQEBAQEBAQAAAAAAAAAAAAAAAAAAAAAAAAAAAQEBAQEBAQEBAQEBAAAAAAAAAAAAAAAAAAAAAAAAAAABAQEBAQEBAQEBAQEAAAAAAAAAAAAAAAAAAAAAAAAAAAEBAQEBAQEBAQEBAQAAAAAAAAAAAAAAAAAAAAAAAAAAAQEBAQEBAQEBAQEBAAAAAAAAAAAAAAAAAAAAAAAAAAABAQEBAQEBAQEBAQEAAAAAAAAAAAAAAAAAAAAAAAAAAAEBAQEBAQEBAQEBAQAAAAAAAAAAAAAAAAAAAQEBAQEBAQEBAQEBAQEBAQEBAAAAAAAAAAAAAAAAAAABAQEBAQEBAQEBAQEBAQEBAQEAAAAAAAAAAAAAAAAAAAEBAQEBAQEBAQEBAQEBAQEBAQAAAAAAAAAAAAAAAAAAAQEBAQEBAQEBAQEBAAAAAAAAAAAAAAAAAAAAAAAAAAABAQEBAQEBAQEBAQEAAAAAAAAAAAAAAAAAAAAAAAAAAAEBAQEBAQEBAQEBAQAAAAAAAAAAAAAAAAAAAQEBAQEBAQEBAQEBAQEBAQEBAAAAAAAAAAAAAAAAAAABAQEBAQEBAQEBAQEBAQEBAQEAAAAAAAAAAAAAAAAAAAEBAQEBAQEBAQEBAQEBAQEBAQAAAAAAAAAAAAAAAAAAAQEBAQEBAQEBAQEBAQEBAQEBAAAAAAAAAAAAAAAAAAABAQEBAQEBAQEBAQEBAQEBAQEAAAAAAAAAAAAAAAAAAAEBAQEBAQEBAQEBAQ==" - }, - "palette" : { - "originalArgb8888" : [ -265674 ], - "convertedRgb565" : [ -122 ] } }, "diagnostics" : [ ] @@ -420,14 +420,14 @@ "last_modified" : 1774359772432, "fingerprint" : "eeb7cc665386299403b7be1c272375d5077f3647c587f8033aa8c9275f840562", "metadata" : { + "palette" : { + "originalArgb8888" : [ -265674 ], + "convertedRgb565" : [ -122 ] + }, "tile" : { "width" : 32, "height" : 32, "paletteIndices" : "AQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAAAAAAAAAAABAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEAAAAAAAAAAAEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQAAAAAAAAAAAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAAAAAAAAAAABAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEAAAAAAAAAAAEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQAAAAAAAAAAAQEBAQEBAQEBAQEBAAAAAAAAAAAAAAAAAAAAAAAAAAABAQEBAQEBAQEBAQEAAAAAAAAAAAAAAAAAAAAAAAAAAAEBAQEBAQEBAQEBAQAAAAAAAAAAAAAAAAAAAAAAAAAAAQEBAQEBAQEBAQEBAAAAAAAAAAAAAAAAAAAAAAAAAAABAQEBAQEBAQEBAQEAAAAAAAAAAAAAAAAAAAAAAAAAAAEBAQEBAQEBAQEBAQAAAAAAAAAAAAAAAAAAAAAAAAAAAQEBAQEBAQEBAQEBAAAAAAAAAAAAAAAAAAAAAAAAAAABAQEBAQEBAQEBAQEAAAAAAAAAAAAAAAAAAAAAAAAAAAEBAQEBAQEBAQEBAQAAAAAAAAAAAAAAAAAAAQEBAQEBAQEBAQEBAQEBAQEBAAAAAAAAAAAAAAAAAAABAQEBAQEBAQEBAQEBAQEBAQEAAAAAAAAAAAAAAAAAAAEBAQEBAQEBAQEBAQEBAQEBAQAAAAAAAAAAAAAAAAAAAQEBAQEBAQEBAQEBAAAAAAAAAAAAAAAAAAAAAAAAAAABAQEBAQEBAQEBAQEAAAAAAAAAAAAAAAAAAAAAAAAAAAEBAQEBAQEBAQEBAQAAAAAAAAAAAAAAAAAAAQEBAQEBAQEBAQEBAQEBAQEBAAAAAAAAAAAAAAAAAAABAQEBAQEBAQEBAQEBAQEBAQEAAAAAAAAAAAAAAAAAAAEBAQEBAQEBAQEBAQEBAQEBAQAAAAAAAAAAAAAAAAAAAQEBAQEBAQEBAQEBAQEBAQEBAAAAAAAAAAAAAAAAAAABAQEBAQEBAQEBAQEBAQEBAQEAAAAAAAAAAAAAAAAAAAEBAQEBAQEBAQEBAQ==" - }, - "palette" : { - "originalArgb8888" : [ -265674 ], - "convertedRgb565" : [ -122 ] } }, "diagnostics" : [ ] @@ -438,14 +438,14 @@ "last_modified" : 1774359772433, "fingerprint" : "eeb7cc665386299403b7be1c272375d5077f3647c587f8033aa8c9275f840562", "metadata" : { + "palette" : { + "originalArgb8888" : [ -265674 ], + "convertedRgb565" : [ -122 ] + }, "tile" : { "width" : 32, "height" : 32, "paletteIndices" : "AQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAAAAAAAAAAABAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEAAAAAAAAAAAEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQAAAAAAAAAAAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAAAAAAAAAAABAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEAAAAAAAAAAAEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQAAAAAAAAAAAQEBAQEBAQEBAQEBAAAAAAAAAAAAAAAAAAAAAAAAAAABAQEBAQEBAQEBAQEAAAAAAAAAAAAAAAAAAAAAAAAAAAEBAQEBAQEBAQEBAQAAAAAAAAAAAAAAAAAAAAAAAAAAAQEBAQEBAQEBAQEBAAAAAAAAAAAAAAAAAAAAAAAAAAABAQEBAQEBAQEBAQEAAAAAAAAAAAAAAAAAAAAAAAAAAAEBAQEBAQEBAQEBAQAAAAAAAAAAAAAAAAAAAAAAAAAAAQEBAQEBAQEBAQEBAAAAAAAAAAAAAAAAAAAAAAAAAAABAQEBAQEBAQEBAQEAAAAAAAAAAAAAAAAAAAAAAAAAAAEBAQEBAQEBAQEBAQAAAAAAAAAAAAAAAAAAAQEBAQEBAQEBAQEBAQEBAQEBAAAAAAAAAAAAAAAAAAABAQEBAQEBAQEBAQEBAQEBAQEAAAAAAAAAAAAAAAAAAAEBAQEBAQEBAQEBAQEBAQEBAQAAAAAAAAAAAAAAAAAAAQEBAQEBAQEBAQEBAAAAAAAAAAAAAAAAAAAAAAAAAAABAQEBAQEBAQEBAQEAAAAAAAAAAAAAAAAAAAAAAAAAAAEBAQEBAQEBAQEBAQAAAAAAAAAAAAAAAAAAAQEBAQEBAQEBAQEBAQEBAQEBAAAAAAAAAAAAAAAAAAABAQEBAQEBAQEBAQEBAQEBAQEAAAAAAAAAAAAAAAAAAAEBAQEBAQEBAQEBAQEBAQEBAQAAAAAAAAAAAAAAAAAAAQEBAQEBAQEBAQEBAQEBAQEBAAAAAAAAAAAAAAAAAAABAQEBAQEBAQEBAQEBAQEBAQEAAAAAAAAAAAAAAAAAAAEBAQEBAQEBAQEBAQ==" - }, - "palette" : { - "originalArgb8888" : [ -265674 ], - "convertedRgb565" : [ -122 ] } }, "diagnostics" : [ ] @@ -456,14 +456,14 @@ "last_modified" : 1774359772435, "fingerprint" : "eeb7cc665386299403b7be1c272375d5077f3647c587f8033aa8c9275f840562", "metadata" : { + "palette" : { + "originalArgb8888" : [ -265674 ], + "convertedRgb565" : [ -122 ] + }, "tile" : { "width" : 32, "height" : 32, "paletteIndices" : "AQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAAAAAAAAAAABAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEAAAAAAAAAAAEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQAAAAAAAAAAAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAAAAAAAAAAABAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEAAAAAAAAAAAEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQAAAAAAAAAAAQEBAQEBAQEBAQEBAAAAAAAAAAAAAAAAAAAAAAAAAAABAQEBAQEBAQEBAQEAAAAAAAAAAAAAAAAAAAAAAAAAAAEBAQEBAQEBAQEBAQAAAAAAAAAAAAAAAAAAAAAAAAAAAQEBAQEBAQEBAQEBAAAAAAAAAAAAAAAAAAAAAAAAAAABAQEBAQEBAQEBAQEAAAAAAAAAAAAAAAAAAAAAAAAAAAEBAQEBAQEBAQEBAQAAAAAAAAAAAAAAAAAAAAAAAAAAAQEBAQEBAQEBAQEBAAAAAAAAAAAAAAAAAAAAAAAAAAABAQEBAQEBAQEBAQEAAAAAAAAAAAAAAAAAAAAAAAAAAAEBAQEBAQEBAQEBAQAAAAAAAAAAAAAAAAAAAQEBAQEBAQEBAQEBAQEBAQEBAAAAAAAAAAAAAAAAAAABAQEBAQEBAQEBAQEBAQEBAQEAAAAAAAAAAAAAAAAAAAEBAQEBAQEBAQEBAQEBAQEBAQAAAAAAAAAAAAAAAAAAAQEBAQEBAQEBAQEBAAAAAAAAAAAAAAAAAAAAAAAAAAABAQEBAQEBAQEBAQEAAAAAAAAAAAAAAAAAAAAAAAAAAAEBAQEBAQEBAQEBAQAAAAAAAAAAAAAAAAAAAQEBAQEBAQEBAQEBAQEBAQEBAAAAAAAAAAAAAAAAAAABAQEBAQEBAQEBAQEBAQEBAQEAAAAAAAAAAAAAAAAAAAEBAQEBAQEBAQEBAQEBAQEBAQAAAAAAAAAAAAAAAAAAAQEBAQEBAQEBAQEBAQEBAQEBAAAAAAAAAAAAAAAAAAABAQEBAQEBAQEBAQEBAQEBAQEAAAAAAAAAAAAAAAAAAAEBAQEBAQEBAQEBAQ==" - }, - "palette" : { - "originalArgb8888" : [ -265674 ], - "convertedRgb565" : [ -122 ] } }, "diagnostics" : [ ] @@ -474,14 +474,14 @@ "last_modified" : 1774359772436, "fingerprint" : "eeb7cc665386299403b7be1c272375d5077f3647c587f8033aa8c9275f840562", "metadata" : { + "palette" : { + "originalArgb8888" : [ -265674 ], + "convertedRgb565" : [ -122 ] + }, "tile" : { "width" : 32, "height" : 32, "paletteIndices" : "AQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAAAAAAAAAAABAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEAAAAAAAAAAAEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQAAAAAAAAAAAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAAAAAAAAAAABAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEAAAAAAAAAAAEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQAAAAAAAAAAAQEBAQEBAQEBAQEBAAAAAAAAAAAAAAAAAAAAAAAAAAABAQEBAQEBAQEBAQEAAAAAAAAAAAAAAAAAAAAAAAAAAAEBAQEBAQEBAQEBAQAAAAAAAAAAAAAAAAAAAAAAAAAAAQEBAQEBAQEBAQEBAAAAAAAAAAAAAAAAAAAAAAAAAAABAQEBAQEBAQEBAQEAAAAAAAAAAAAAAAAAAAAAAAAAAAEBAQEBAQEBAQEBAQAAAAAAAAAAAAAAAAAAAAAAAAAAAQEBAQEBAQEBAQEBAAAAAAAAAAAAAAAAAAAAAAAAAAABAQEBAQEBAQEBAQEAAAAAAAAAAAAAAAAAAAAAAAAAAAEBAQEBAQEBAQEBAQAAAAAAAAAAAAAAAAAAAQEBAQEBAQEBAQEBAQEBAQEBAAAAAAAAAAAAAAAAAAABAQEBAQEBAQEBAQEBAQEBAQEAAAAAAAAAAAAAAAAAAAEBAQEBAQEBAQEBAQEBAQEBAQAAAAAAAAAAAAAAAAAAAQEBAQEBAQEBAQEBAAAAAAAAAAAAAAAAAAAAAAAAAAABAQEBAQEBAQEBAQEAAAAAAAAAAAAAAAAAAAAAAAAAAAEBAQEBAQEBAQEBAQAAAAAAAAAAAAAAAAAAAQEBAQEBAQEBAQEBAQEBAQEBAAAAAAAAAAAAAAAAAAABAQEBAQEBAQEBAQEBAQEBAQEAAAAAAAAAAAAAAAAAAAEBAQEBAQEBAQEBAQEBAQEBAQAAAAAAAAAAAAAAAAAAAQEBAQEBAQEBAQEBAQEBAQEBAAAAAAAAAAAAAAAAAAABAQEBAQEBAQEBAQEBAQEBAQEAAAAAAAAAAAAAAAAAAAEBAQEBAQEBAQEBAQ==" - }, - "palette" : { - "originalArgb8888" : [ -265674 ], - "convertedRgb565" : [ -122 ] } }, "diagnostics" : [ ] @@ -492,14 +492,14 @@ "last_modified" : 1774359772437, "fingerprint" : "eeb7cc665386299403b7be1c272375d5077f3647c587f8033aa8c9275f840562", "metadata" : { + "palette" : { + "originalArgb8888" : [ -265674 ], + "convertedRgb565" : [ -122 ] + }, "tile" : { "width" : 32, "height" : 32, "paletteIndices" : "AQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAAAAAAAAAAABAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEAAAAAAAAAAAEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQAAAAAAAAAAAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAAAAAAAAAAABAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEAAAAAAAAAAAEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQAAAAAAAAAAAQEBAQEBAQEBAQEBAAAAAAAAAAAAAAAAAAAAAAAAAAABAQEBAQEBAQEBAQEAAAAAAAAAAAAAAAAAAAAAAAAAAAEBAQEBAQEBAQEBAQAAAAAAAAAAAAAAAAAAAAAAAAAAAQEBAQEBAQEBAQEBAAAAAAAAAAAAAAAAAAAAAAAAAAABAQEBAQEBAQEBAQEAAAAAAAAAAAAAAAAAAAAAAAAAAAEBAQEBAQEBAQEBAQAAAAAAAAAAAAAAAAAAAAAAAAAAAQEBAQEBAQEBAQEBAAAAAAAAAAAAAAAAAAAAAAAAAAABAQEBAQEBAQEBAQEAAAAAAAAAAAAAAAAAAAAAAAAAAAEBAQEBAQEBAQEBAQAAAAAAAAAAAAAAAAAAAQEBAQEBAQEBAQEBAQEBAQEBAAAAAAAAAAAAAAAAAAABAQEBAQEBAQEBAQEBAQEBAQEAAAAAAAAAAAAAAAAAAAEBAQEBAQEBAQEBAQEBAQEBAQAAAAAAAAAAAAAAAAAAAQEBAQEBAQEBAQEBAAAAAAAAAAAAAAAAAAAAAAAAAAABAQEBAQEBAQEBAQEAAAAAAAAAAAAAAAAAAAAAAAAAAAEBAQEBAQEBAQEBAQAAAAAAAAAAAAAAAAAAAQEBAQEBAQEBAQEBAQEBAQEBAAAAAAAAAAAAAAAAAAABAQEBAQEBAQEBAQEBAQEBAQEAAAAAAAAAAAAAAAAAAAEBAQEBAQEBAQEBAQEBAQEBAQAAAAAAAAAAAAAAAAAAAQEBAQEBAQEBAQEBAQEBAQEBAAAAAAAAAAAAAAAAAAABAQEBAQEBAQEBAQEBAQEBAQEAAAAAAAAAAAAAAAAAAAEBAQEBAQEBAQEBAQ==" - }, - "palette" : { - "originalArgb8888" : [ -265674 ], - "convertedRgb565" : [ -122 ] } }, "diagnostics" : [ ] @@ -510,14 +510,14 @@ "last_modified" : 1774359772438, "fingerprint" : "eeb7cc665386299403b7be1c272375d5077f3647c587f8033aa8c9275f840562", "metadata" : { + "palette" : { + "originalArgb8888" : [ -265674 ], + "convertedRgb565" : [ -122 ] + }, "tile" : { "width" : 32, "height" : 32, "paletteIndices" : "AQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAAAAAAAAAAABAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEAAAAAAAAAAAEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQAAAAAAAAAAAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAAAAAAAAAAABAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEAAAAAAAAAAAEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQAAAAAAAAAAAQEBAQEBAQEBAQEBAAAAAAAAAAAAAAAAAAAAAAAAAAABAQEBAQEBAQEBAQEAAAAAAAAAAAAAAAAAAAAAAAAAAAEBAQEBAQEBAQEBAQAAAAAAAAAAAAAAAAAAAAAAAAAAAQEBAQEBAQEBAQEBAAAAAAAAAAAAAAAAAAAAAAAAAAABAQEBAQEBAQEBAQEAAAAAAAAAAAAAAAAAAAAAAAAAAAEBAQEBAQEBAQEBAQAAAAAAAAAAAAAAAAAAAAAAAAAAAQEBAQEBAQEBAQEBAAAAAAAAAAAAAAAAAAAAAAAAAAABAQEBAQEBAQEBAQEAAAAAAAAAAAAAAAAAAAAAAAAAAAEBAQEBAQEBAQEBAQAAAAAAAAAAAAAAAAAAAQEBAQEBAQEBAQEBAQEBAQEBAAAAAAAAAAAAAAAAAAABAQEBAQEBAQEBAQEBAQEBAQEAAAAAAAAAAAAAAAAAAAEBAQEBAQEBAQEBAQEBAQEBAQAAAAAAAAAAAAAAAAAAAQEBAQEBAQEBAQEBAAAAAAAAAAAAAAAAAAAAAAAAAAABAQEBAQEBAQEBAQEAAAAAAAAAAAAAAAAAAAAAAAAAAAEBAQEBAQEBAQEBAQAAAAAAAAAAAAAAAAAAAQEBAQEBAQEBAQEBAQEBAQEBAAAAAAAAAAAAAAAAAAABAQEBAQEBAQEBAQEBAQEBAQEAAAAAAAAAAAAAAAAAAAEBAQEBAQEBAQEBAQEBAQEBAQAAAAAAAAAAAAAAAAAAAQEBAQEBAQEBAQEBAQEBAQEBAAAAAAAAAAAAAAAAAAABAQEBAQEBAQEBAQEBAQEBAQEAAAAAAAAAAAAAAAAAAAEBAQEBAQEBAQEBAQ==" - }, - "palette" : { - "originalArgb8888" : [ -265674 ], - "convertedRgb565" : [ -122 ] } }, "diagnostics" : [ ] @@ -528,14 +528,14 @@ "last_modified" : 1774359772439, "fingerprint" : "eeb7cc665386299403b7be1c272375d5077f3647c587f8033aa8c9275f840562", "metadata" : { + "palette" : { + "originalArgb8888" : [ -265674 ], + "convertedRgb565" : [ -122 ] + }, "tile" : { "width" : 32, "height" : 32, "paletteIndices" : "AQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAAAAAAAAAAABAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEAAAAAAAAAAAEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQAAAAAAAAAAAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAAAAAAAAAAABAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEAAAAAAAAAAAEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQAAAAAAAAAAAQEBAQEBAQEBAQEBAAAAAAAAAAAAAAAAAAAAAAAAAAABAQEBAQEBAQEBAQEAAAAAAAAAAAAAAAAAAAAAAAAAAAEBAQEBAQEBAQEBAQAAAAAAAAAAAAAAAAAAAAAAAAAAAQEBAQEBAQEBAQEBAAAAAAAAAAAAAAAAAAAAAAAAAAABAQEBAQEBAQEBAQEAAAAAAAAAAAAAAAAAAAAAAAAAAAEBAQEBAQEBAQEBAQAAAAAAAAAAAAAAAAAAAAAAAAAAAQEBAQEBAQEBAQEBAAAAAAAAAAAAAAAAAAAAAAAAAAABAQEBAQEBAQEBAQEAAAAAAAAAAAAAAAAAAAAAAAAAAAEBAQEBAQEBAQEBAQAAAAAAAAAAAAAAAAAAAQEBAQEBAQEBAQEBAQEBAQEBAAAAAAAAAAAAAAAAAAABAQEBAQEBAQEBAQEBAQEBAQEAAAAAAAAAAAAAAAAAAAEBAQEBAQEBAQEBAQEBAQEBAQAAAAAAAAAAAAAAAAAAAQEBAQEBAQEBAQEBAAAAAAAAAAAAAAAAAAAAAAAAAAABAQEBAQEBAQEBAQEAAAAAAAAAAAAAAAAAAAAAAAAAAAEBAQEBAQEBAQEBAQAAAAAAAAAAAAAAAAAAAQEBAQEBAQEBAQEBAQEBAQEBAAAAAAAAAAAAAAAAAAABAQEBAQEBAQEBAQEBAQEBAQEAAAAAAAAAAAAAAAAAAAEBAQEBAQEBAQEBAQEBAQEBAQAAAAAAAAAAAAAAAAAAAQEBAQEBAQEBAQEBAQEBAQEBAAAAAAAAAAAAAAAAAAABAQEBAQEBAQEBAQEBAQEBAQEAAAAAAAAAAAAAAAAAAAEBAQEBAQEBAQEBAQ==" - }, - "palette" : { - "originalArgb8888" : [ -265674 ], - "convertedRgb565" : [ -122 ] } }, "diagnostics" : [ ] @@ -546,14 +546,14 @@ "last_modified" : 1774359772441, "fingerprint" : "eeb7cc665386299403b7be1c272375d5077f3647c587f8033aa8c9275f840562", "metadata" : { + "palette" : { + "originalArgb8888" : [ -265674 ], + "convertedRgb565" : [ -122 ] + }, "tile" : { "width" : 32, "height" : 32, "paletteIndices" : "AQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAAAAAAAAAAABAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEAAAAAAAAAAAEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQAAAAAAAAAAAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAAAAAAAAAAABAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEAAAAAAAAAAAEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQAAAAAAAAAAAQEBAQEBAQEBAQEBAAAAAAAAAAAAAAAAAAAAAAAAAAABAQEBAQEBAQEBAQEAAAAAAAAAAAAAAAAAAAAAAAAAAAEBAQEBAQEBAQEBAQAAAAAAAAAAAAAAAAAAAAAAAAAAAQEBAQEBAQEBAQEBAAAAAAAAAAAAAAAAAAAAAAAAAAABAQEBAQEBAQEBAQEAAAAAAAAAAAAAAAAAAAAAAAAAAAEBAQEBAQEBAQEBAQAAAAAAAAAAAAAAAAAAAAAAAAAAAQEBAQEBAQEBAQEBAAAAAAAAAAAAAAAAAAAAAAAAAAABAQEBAQEBAQEBAQEAAAAAAAAAAAAAAAAAAAAAAAAAAAEBAQEBAQEBAQEBAQAAAAAAAAAAAAAAAAAAAQEBAQEBAQEBAQEBAQEBAQEBAAAAAAAAAAAAAAAAAAABAQEBAQEBAQEBAQEBAQEBAQEAAAAAAAAAAAAAAAAAAAEBAQEBAQEBAQEBAQEBAQEBAQAAAAAAAAAAAAAAAAAAAQEBAQEBAQEBAQEBAAAAAAAAAAAAAAAAAAAAAAAAAAABAQEBAQEBAQEBAQEAAAAAAAAAAAAAAAAAAAAAAAAAAAEBAQEBAQEBAQEBAQAAAAAAAAAAAAAAAAAAAQEBAQEBAQEBAQEBAQEBAQEBAAAAAAAAAAAAAAAAAAABAQEBAQEBAQEBAQEBAQEBAQEAAAAAAAAAAAAAAAAAAAEBAQEBAQEBAQEBAQEBAQEBAQAAAAAAAAAAAAAAAAAAAQEBAQEBAQEBAQEBAQEBAQEBAAAAAAAAAAAAAAAAAAABAQEBAQEBAQEBAQEBAQEBAQEAAAAAAAAAAAAAAAAAAAEBAQEBAQEBAQEBAQ==" - }, - "palette" : { - "originalArgb8888" : [ -265674 ], - "convertedRgb565" : [ -122 ] } }, "diagnostics" : [ ] @@ -564,14 +564,14 @@ "last_modified" : 1774359772442, "fingerprint" : "eeb7cc665386299403b7be1c272375d5077f3647c587f8033aa8c9275f840562", "metadata" : { + "palette" : { + "originalArgb8888" : [ -265674 ], + "convertedRgb565" : [ -122 ] + }, "tile" : { "width" : 32, "height" : 32, "paletteIndices" : "AQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAAAAAAAAAAABAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEAAAAAAAAAAAEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQAAAAAAAAAAAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAAAAAAAAAAABAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEAAAAAAAAAAAEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQAAAAAAAAAAAQEBAQEBAQEBAQEBAAAAAAAAAAAAAAAAAAAAAAAAAAABAQEBAQEBAQEBAQEAAAAAAAAAAAAAAAAAAAAAAAAAAAEBAQEBAQEBAQEBAQAAAAAAAAAAAAAAAAAAAAAAAAAAAQEBAQEBAQEBAQEBAAAAAAAAAAAAAAAAAAAAAAAAAAABAQEBAQEBAQEBAQEAAAAAAAAAAAAAAAAAAAAAAAAAAAEBAQEBAQEBAQEBAQAAAAAAAAAAAAAAAAAAAAAAAAAAAQEBAQEBAQEBAQEBAAAAAAAAAAAAAAAAAAAAAAAAAAABAQEBAQEBAQEBAQEAAAAAAAAAAAAAAAAAAAAAAAAAAAEBAQEBAQEBAQEBAQAAAAAAAAAAAAAAAAAAAQEBAQEBAQEBAQEBAQEBAQEBAAAAAAAAAAAAAAAAAAABAQEBAQEBAQEBAQEBAQEBAQEAAAAAAAAAAAAAAAAAAAEBAQEBAQEBAQEBAQEBAQEBAQAAAAAAAAAAAAAAAAAAAQEBAQEBAQEBAQEBAAAAAAAAAAAAAAAAAAAAAAAAAAABAQEBAQEBAQEBAQEAAAAAAAAAAAAAAAAAAAAAAAAAAAEBAQEBAQEBAQEBAQAAAAAAAAAAAAAAAAAAAQEBAQEBAQEBAQEBAQEBAQEBAAAAAAAAAAAAAAAAAAABAQEBAQEBAQEBAQEBAQEBAQEAAAAAAAAAAAAAAAAAAAEBAQEBAQEBAQEBAQEBAQEBAQAAAAAAAAAAAAAAAAAAAQEBAQEBAQEBAQEBAQEBAQEBAAAAAAAAAAAAAAAAAAABAQEBAQEBAQEBAQEBAQEBAQEAAAAAAAAAAAAAAAAAAAEBAQEBAQEBAQEBAQ==" - }, - "palette" : { - "originalArgb8888" : [ -265674 ], - "convertedRgb565" : [ -122 ] } }, "diagnostics" : [ ] @@ -582,14 +582,14 @@ "last_modified" : 1774359772443, "fingerprint" : "eeb7cc665386299403b7be1c272375d5077f3647c587f8033aa8c9275f840562", "metadata" : { + "palette" : { + "originalArgb8888" : [ -265674 ], + "convertedRgb565" : [ -122 ] + }, "tile" : { "width" : 32, "height" : 32, "paletteIndices" : "AQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAAAAAAAAAAABAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEAAAAAAAAAAAEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQAAAAAAAAAAAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAAAAAAAAAAABAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEAAAAAAAAAAAEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQAAAAAAAAAAAQEBAQEBAQEBAQEBAAAAAAAAAAAAAAAAAAAAAAAAAAABAQEBAQEBAQEBAQEAAAAAAAAAAAAAAAAAAAAAAAAAAAEBAQEBAQEBAQEBAQAAAAAAAAAAAAAAAAAAAAAAAAAAAQEBAQEBAQEBAQEBAAAAAAAAAAAAAAAAAAAAAAAAAAABAQEBAQEBAQEBAQEAAAAAAAAAAAAAAAAAAAAAAAAAAAEBAQEBAQEBAQEBAQAAAAAAAAAAAAAAAAAAAAAAAAAAAQEBAQEBAQEBAQEBAAAAAAAAAAAAAAAAAAAAAAAAAAABAQEBAQEBAQEBAQEAAAAAAAAAAAAAAAAAAAAAAAAAAAEBAQEBAQEBAQEBAQAAAAAAAAAAAAAAAAAAAQEBAQEBAQEBAQEBAQEBAQEBAAAAAAAAAAAAAAAAAAABAQEBAQEBAQEBAQEBAQEBAQEAAAAAAAAAAAAAAAAAAAEBAQEBAQEBAQEBAQEBAQEBAQAAAAAAAAAAAAAAAAAAAQEBAQEBAQEBAQEBAAAAAAAAAAAAAAAAAAAAAAAAAAABAQEBAQEBAQEBAQEAAAAAAAAAAAAAAAAAAAAAAAAAAAEBAQEBAQEBAQEBAQAAAAAAAAAAAAAAAAAAAQEBAQEBAQEBAQEBAQEBAQEBAAAAAAAAAAAAAAAAAAABAQEBAQEBAQEBAQEBAQEBAQEAAAAAAAAAAAAAAAAAAAEBAQEBAQEBAQEBAQEBAQEBAQAAAAAAAAAAAAAAAAAAAQEBAQEBAQEBAQEBAQEBAQEBAAAAAAAAAAAAAAAAAAABAQEBAQEBAQEBAQEBAQEBAQEAAAAAAAAAAAAAAAAAAAEBAQEBAQEBAQEBAQ==" - }, - "palette" : { - "originalArgb8888" : [ -265674 ], - "convertedRgb565" : [ -122 ] } }, "diagnostics" : [ ] @@ -600,14 +600,14 @@ "last_modified" : 1774359772444, "fingerprint" : "eeb7cc665386299403b7be1c272375d5077f3647c587f8033aa8c9275f840562", "metadata" : { + "palette" : { + "originalArgb8888" : [ -265674 ], + "convertedRgb565" : [ -122 ] + }, "tile" : { "width" : 32, "height" : 32, "paletteIndices" : "AQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAAAAAAAAAAABAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEAAAAAAAAAAAEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQAAAAAAAAAAAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAAAAAAAAAAABAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEAAAAAAAAAAAEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQAAAAAAAAAAAQEBAQEBAQEBAQEBAAAAAAAAAAAAAAAAAAAAAAAAAAABAQEBAQEBAQEBAQEAAAAAAAAAAAAAAAAAAAAAAAAAAAEBAQEBAQEBAQEBAQAAAAAAAAAAAAAAAAAAAAAAAAAAAQEBAQEBAQEBAQEBAAAAAAAAAAAAAAAAAAAAAAAAAAABAQEBAQEBAQEBAQEAAAAAAAAAAAAAAAAAAAAAAAAAAAEBAQEBAQEBAQEBAQAAAAAAAAAAAAAAAAAAAAAAAAAAAQEBAQEBAQEBAQEBAAAAAAAAAAAAAAAAAAAAAAAAAAABAQEBAQEBAQEBAQEAAAAAAAAAAAAAAAAAAAAAAAAAAAEBAQEBAQEBAQEBAQAAAAAAAAAAAAAAAAAAAQEBAQEBAQEBAQEBAQEBAQEBAAAAAAAAAAAAAAAAAAABAQEBAQEBAQEBAQEBAQEBAQEAAAAAAAAAAAAAAAAAAAEBAQEBAQEBAQEBAQEBAQEBAQAAAAAAAAAAAAAAAAAAAQEBAQEBAQEBAQEBAAAAAAAAAAAAAAAAAAAAAAAAAAABAQEBAQEBAQEBAQEAAAAAAAAAAAAAAAAAAAAAAAAAAAEBAQEBAQEBAQEBAQAAAAAAAAAAAAAAAAAAAQEBAQEBAQEBAQEBAQEBAQEBAAAAAAAAAAAAAAAAAAABAQEBAQEBAQEBAQEBAQEBAQEAAAAAAAAAAAAAAAAAAAEBAQEBAQEBAQEBAQEBAQEBAQAAAAAAAAAAAAAAAAAAAQEBAQEBAQEBAQEBAQEBAQEBAAAAAAAAAAAAAAAAAAABAQEBAQEBAQEBAQEBAQEBAQEAAAAAAAAAAAAAAAAAAAEBAQEBAQEBAQEBAQ==" - }, - "palette" : { - "originalArgb8888" : [ -265674 ], - "convertedRgb565" : [ -122 ] } }, "diagnostics" : [ ] @@ -618,14 +618,14 @@ "last_modified" : 1774359772445, "fingerprint" : "eeb7cc665386299403b7be1c272375d5077f3647c587f8033aa8c9275f840562", "metadata" : { + "palette" : { + "originalArgb8888" : [ -265674 ], + "convertedRgb565" : [ -122 ] + }, "tile" : { "width" : 32, "height" : 32, "paletteIndices" : "AQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAAAAAAAAAAABAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEAAAAAAAAAAAEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQAAAAAAAAAAAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAAAAAAAAAAABAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEAAAAAAAAAAAEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQAAAAAAAAAAAQEBAQEBAQEBAQEBAAAAAAAAAAAAAAAAAAAAAAAAAAABAQEBAQEBAQEBAQEAAAAAAAAAAAAAAAAAAAAAAAAAAAEBAQEBAQEBAQEBAQAAAAAAAAAAAAAAAAAAAAAAAAAAAQEBAQEBAQEBAQEBAAAAAAAAAAAAAAAAAAAAAAAAAAABAQEBAQEBAQEBAQEAAAAAAAAAAAAAAAAAAAAAAAAAAAEBAQEBAQEBAQEBAQAAAAAAAAAAAAAAAAAAAAAAAAAAAQEBAQEBAQEBAQEBAAAAAAAAAAAAAAAAAAAAAAAAAAABAQEBAQEBAQEBAQEAAAAAAAAAAAAAAAAAAAAAAAAAAAEBAQEBAQEBAQEBAQAAAAAAAAAAAAAAAAAAAQEBAQEBAQEBAQEBAQEBAQEBAAAAAAAAAAAAAAAAAAABAQEBAQEBAQEBAQEBAQEBAQEAAAAAAAAAAAAAAAAAAAEBAQEBAQEBAQEBAQEBAQEBAQAAAAAAAAAAAAAAAAAAAQEBAQEBAQEBAQEBAAAAAAAAAAAAAAAAAAAAAAAAAAABAQEBAQEBAQEBAQEAAAAAAAAAAAAAAAAAAAAAAAAAAAEBAQEBAQEBAQEBAQAAAAAAAAAAAAAAAAAAAQEBAQEBAQEBAQEBAQEBAQEBAAAAAAAAAAAAAAAAAAABAQEBAQEBAQEBAQEBAQEBAQEAAAAAAAAAAAAAAAAAAAEBAQEBAQEBAQEBAQEBAQEBAQAAAAAAAAAAAAAAAAAAAQEBAQEBAQEBAQEBAQEBAQEBAAAAAAAAAAAAAAAAAAABAQEBAQEBAQEBAQEBAQEBAQEAAAAAAAAAAAAAAAAAAAEBAQEBAQEBAQEBAQ==" - }, - "palette" : { - "originalArgb8888" : [ -265674 ], - "convertedRgb565" : [ -122 ] } }, "diagnostics" : [ ] @@ -636,14 +636,14 @@ "last_modified" : 1774359772448, "fingerprint" : "eeb7cc665386299403b7be1c272375d5077f3647c587f8033aa8c9275f840562", "metadata" : { + "palette" : { + "originalArgb8888" : [ -265674 ], + "convertedRgb565" : [ -122 ] + }, "tile" : { "width" : 32, "height" : 32, "paletteIndices" : "AQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAAAAAAAAAAABAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEAAAAAAAAAAAEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQAAAAAAAAAAAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAAAAAAAAAAABAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEAAAAAAAAAAAEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQAAAAAAAAAAAQEBAQEBAQEBAQEBAAAAAAAAAAAAAAAAAAAAAAAAAAABAQEBAQEBAQEBAQEAAAAAAAAAAAAAAAAAAAAAAAAAAAEBAQEBAQEBAQEBAQAAAAAAAAAAAAAAAAAAAAAAAAAAAQEBAQEBAQEBAQEBAAAAAAAAAAAAAAAAAAAAAAAAAAABAQEBAQEBAQEBAQEAAAAAAAAAAAAAAAAAAAAAAAAAAAEBAQEBAQEBAQEBAQAAAAAAAAAAAAAAAAAAAAAAAAAAAQEBAQEBAQEBAQEBAAAAAAAAAAAAAAAAAAAAAAAAAAABAQEBAQEBAQEBAQEAAAAAAAAAAAAAAAAAAAAAAAAAAAEBAQEBAQEBAQEBAQAAAAAAAAAAAAAAAAAAAQEBAQEBAQEBAQEBAQEBAQEBAAAAAAAAAAAAAAAAAAABAQEBAQEBAQEBAQEBAQEBAQEAAAAAAAAAAAAAAAAAAAEBAQEBAQEBAQEBAQEBAQEBAQAAAAAAAAAAAAAAAAAAAQEBAQEBAQEBAQEBAAAAAAAAAAAAAAAAAAAAAAAAAAABAQEBAQEBAQEBAQEAAAAAAAAAAAAAAAAAAAAAAAAAAAEBAQEBAQEBAQEBAQAAAAAAAAAAAAAAAAAAAQEBAQEBAQEBAQEBAQEBAQEBAAAAAAAAAAAAAAAAAAABAQEBAQEBAQEBAQEBAQEBAQEAAAAAAAAAAAAAAAAAAAEBAQEBAQEBAQEBAQEBAQEBAQAAAAAAAAAAAAAAAAAAAQEBAQEBAQEBAQEBAQEBAQEBAAAAAAAAAAAAAAAAAAABAQEBAQEBAQEBAQEBAQEBAQEAAAAAAAAAAAAAAAAAAAEBAQEBAQEBAQEBAQ==" - }, - "palette" : { - "originalArgb8888" : [ -265674 ], - "convertedRgb565" : [ -122 ] } }, "diagnostics" : [ ] @@ -654,14 +654,14 @@ "last_modified" : 1774359772449, "fingerprint" : "eeb7cc665386299403b7be1c272375d5077f3647c587f8033aa8c9275f840562", "metadata" : { + "palette" : { + "originalArgb8888" : [ -265674 ], + "convertedRgb565" : [ -122 ] + }, "tile" : { "width" : 32, "height" : 32, "paletteIndices" : "AQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAAAAAAAAAAABAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEAAAAAAAAAAAEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQAAAAAAAAAAAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAAAAAAAAAAABAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEAAAAAAAAAAAEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQAAAAAAAAAAAQEBAQEBAQEBAQEBAAAAAAAAAAAAAAAAAAAAAAAAAAABAQEBAQEBAQEBAQEAAAAAAAAAAAAAAAAAAAAAAAAAAAEBAQEBAQEBAQEBAQAAAAAAAAAAAAAAAAAAAAAAAAAAAQEBAQEBAQEBAQEBAAAAAAAAAAAAAAAAAAAAAAAAAAABAQEBAQEBAQEBAQEAAAAAAAAAAAAAAAAAAAAAAAAAAAEBAQEBAQEBAQEBAQAAAAAAAAAAAAAAAAAAAAAAAAAAAQEBAQEBAQEBAQEBAAAAAAAAAAAAAAAAAAAAAAAAAAABAQEBAQEBAQEBAQEAAAAAAAAAAAAAAAAAAAAAAAAAAAEBAQEBAQEBAQEBAQAAAAAAAAAAAAAAAAAAAQEBAQEBAQEBAQEBAQEBAQEBAAAAAAAAAAAAAAAAAAABAQEBAQEBAQEBAQEBAQEBAQEAAAAAAAAAAAAAAAAAAAEBAQEBAQEBAQEBAQEBAQEBAQAAAAAAAAAAAAAAAAAAAQEBAQEBAQEBAQEBAAAAAAAAAAAAAAAAAAAAAAAAAAABAQEBAQEBAQEBAQEAAAAAAAAAAAAAAAAAAAAAAAAAAAEBAQEBAQEBAQEBAQAAAAAAAAAAAAAAAAAAAQEBAQEBAQEBAQEBAQEBAQEBAAAAAAAAAAAAAAAAAAABAQEBAQEBAQEBAQEBAQEBAQEAAAAAAAAAAAAAAAAAAAEBAQEBAQEBAQEBAQEBAQEBAQAAAAAAAAAAAAAAAAAAAQEBAQEBAQEBAQEBAQEBAQEBAAAAAAAAAAAAAAAAAAABAQEBAQEBAQEBAQEBAQEBAQEAAAAAAAAAAAAAAAAAAAEBAQEBAQEBAQEBAQ==" - }, - "palette" : { - "originalArgb8888" : [ -265674 ], - "convertedRgb565" : [ -122 ] } }, "diagnostics" : [ ] @@ -672,14 +672,14 @@ "last_modified" : 1774359772450, "fingerprint" : "eeb7cc665386299403b7be1c272375d5077f3647c587f8033aa8c9275f840562", "metadata" : { + "palette" : { + "originalArgb8888" : [ -265674 ], + "convertedRgb565" : [ -122 ] + }, "tile" : { "width" : 32, "height" : 32, "paletteIndices" : "AQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAAAAAAAAAAABAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEAAAAAAAAAAAEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQAAAAAAAAAAAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAAAAAAAAAAABAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEAAAAAAAAAAAEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQAAAAAAAAAAAQEBAQEBAQEBAQEBAAAAAAAAAAAAAAAAAAAAAAAAAAABAQEBAQEBAQEBAQEAAAAAAAAAAAAAAAAAAAAAAAAAAAEBAQEBAQEBAQEBAQAAAAAAAAAAAAAAAAAAAAAAAAAAAQEBAQEBAQEBAQEBAAAAAAAAAAAAAAAAAAAAAAAAAAABAQEBAQEBAQEBAQEAAAAAAAAAAAAAAAAAAAAAAAAAAAEBAQEBAQEBAQEBAQAAAAAAAAAAAAAAAAAAAAAAAAAAAQEBAQEBAQEBAQEBAAAAAAAAAAAAAAAAAAAAAAAAAAABAQEBAQEBAQEBAQEAAAAAAAAAAAAAAAAAAAAAAAAAAAEBAQEBAQEBAQEBAQAAAAAAAAAAAAAAAAAAAQEBAQEBAQEBAQEBAQEBAQEBAAAAAAAAAAAAAAAAAAABAQEBAQEBAQEBAQEBAQEBAQEAAAAAAAAAAAAAAAAAAAEBAQEBAQEBAQEBAQEBAQEBAQAAAAAAAAAAAAAAAAAAAQEBAQEBAQEBAQEBAAAAAAAAAAAAAAAAAAAAAAAAAAABAQEBAQEBAQEBAQEAAAAAAAAAAAAAAAAAAAAAAAAAAAEBAQEBAQEBAQEBAQAAAAAAAAAAAAAAAAAAAQEBAQEBAQEBAQEBAQEBAQEBAAAAAAAAAAAAAAAAAAABAQEBAQEBAQEBAQEBAQEBAQEAAAAAAAAAAAAAAAAAAAEBAQEBAQEBAQEBAQEBAQEBAQAAAAAAAAAAAAAAAAAAAQEBAQEBAQEBAQEBAQEBAQEBAAAAAAAAAAAAAAAAAAABAQEBAQEBAQEBAQEBAQEBAQEAAAAAAAAAAAAAAAAAAAEBAQEBAQEBAQEBAQ==" - }, - "palette" : { - "originalArgb8888" : [ -265674 ], - "convertedRgb565" : [ -122 ] } }, "diagnostics" : [ ] @@ -690,14 +690,14 @@ "last_modified" : 1774359772452, "fingerprint" : "eeb7cc665386299403b7be1c272375d5077f3647c587f8033aa8c9275f840562", "metadata" : { + "palette" : { + "originalArgb8888" : [ -265674 ], + "convertedRgb565" : [ -122 ] + }, "tile" : { "width" : 32, "height" : 32, "paletteIndices" : "AQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAAAAAAAAAAABAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEAAAAAAAAAAAEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQAAAAAAAAAAAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAAAAAAAAAAABAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEAAAAAAAAAAAEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQAAAAAAAAAAAQEBAQEBAQEBAQEBAAAAAAAAAAAAAAAAAAAAAAAAAAABAQEBAQEBAQEBAQEAAAAAAAAAAAAAAAAAAAAAAAAAAAEBAQEBAQEBAQEBAQAAAAAAAAAAAAAAAAAAAAAAAAAAAQEBAQEBAQEBAQEBAAAAAAAAAAAAAAAAAAAAAAAAAAABAQEBAQEBAQEBAQEAAAAAAAAAAAAAAAAAAAAAAAAAAAEBAQEBAQEBAQEBAQAAAAAAAAAAAAAAAAAAAAAAAAAAAQEBAQEBAQEBAQEBAAAAAAAAAAAAAAAAAAAAAAAAAAABAQEBAQEBAQEBAQEAAAAAAAAAAAAAAAAAAAAAAAAAAAEBAQEBAQEBAQEBAQAAAAAAAAAAAAAAAAAAAQEBAQEBAQEBAQEBAQEBAQEBAAAAAAAAAAAAAAAAAAABAQEBAQEBAQEBAQEBAQEBAQEAAAAAAAAAAAAAAAAAAAEBAQEBAQEBAQEBAQEBAQEBAQAAAAAAAAAAAAAAAAAAAQEBAQEBAQEBAQEBAAAAAAAAAAAAAAAAAAAAAAAAAAABAQEBAQEBAQEBAQEAAAAAAAAAAAAAAAAAAAAAAAAAAAEBAQEBAQEBAQEBAQAAAAAAAAAAAAAAAAAAAQEBAQEBAQEBAQEBAQEBAQEBAAAAAAAAAAAAAAAAAAABAQEBAQEBAQEBAQEBAQEBAQEAAAAAAAAAAAAAAAAAAAEBAQEBAQEBAQEBAQEBAQEBAQAAAAAAAAAAAAAAAAAAAQEBAQEBAQEBAQEBAQEBAQEBAAAAAAAAAAAAAAAAAAABAQEBAQEBAQEBAQEBAQEBAQEAAAAAAAAAAAAAAAAAAAEBAQEBAQEBAQEBAQ==" - }, - "palette" : { - "originalArgb8888" : [ -265674 ], - "convertedRgb565" : [ -122 ] } }, "diagnostics" : [ ] @@ -708,14 +708,14 @@ "last_modified" : 1774359772453, "fingerprint" : "eeb7cc665386299403b7be1c272375d5077f3647c587f8033aa8c9275f840562", "metadata" : { + "palette" : { + "originalArgb8888" : [ -265674 ], + "convertedRgb565" : [ -122 ] + }, "tile" : { "width" : 32, "height" : 32, "paletteIndices" : "AQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAAAAAAAAAAABAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEAAAAAAAAAAAEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQAAAAAAAAAAAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAAAAAAAAAAABAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEAAAAAAAAAAAEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQAAAAAAAAAAAQEBAQEBAQEBAQEBAAAAAAAAAAAAAAAAAAAAAAAAAAABAQEBAQEBAQEBAQEAAAAAAAAAAAAAAAAAAAAAAAAAAAEBAQEBAQEBAQEBAQAAAAAAAAAAAAAAAAAAAAAAAAAAAQEBAQEBAQEBAQEBAAAAAAAAAAAAAAAAAAAAAAAAAAABAQEBAQEBAQEBAQEAAAAAAAAAAAAAAAAAAAAAAAAAAAEBAQEBAQEBAQEBAQAAAAAAAAAAAAAAAAAAAAAAAAAAAQEBAQEBAQEBAQEBAAAAAAAAAAAAAAAAAAAAAAAAAAABAQEBAQEBAQEBAQEAAAAAAAAAAAAAAAAAAAAAAAAAAAEBAQEBAQEBAQEBAQAAAAAAAAAAAAAAAAAAAQEBAQEBAQEBAQEBAQEBAQEBAAAAAAAAAAAAAAAAAAABAQEBAQEBAQEBAQEBAQEBAQEAAAAAAAAAAAAAAAAAAAEBAQEBAQEBAQEBAQEBAQEBAQAAAAAAAAAAAAAAAAAAAQEBAQEBAQEBAQEBAAAAAAAAAAAAAAAAAAAAAAAAAAABAQEBAQEBAQEBAQEAAAAAAAAAAAAAAAAAAAAAAAAAAAEBAQEBAQEBAQEBAQAAAAAAAAAAAAAAAAAAAQEBAQEBAQEBAQEBAQEBAQEBAAAAAAAAAAAAAAAAAAABAQEBAQEBAQEBAQEBAQEBAQEAAAAAAAAAAAAAAAAAAAEBAQEBAQEBAQEBAQEBAQEBAQAAAAAAAAAAAAAAAAAAAQEBAQEBAQEBAQEBAQEBAQEBAAAAAAAAAAAAAAAAAAABAQEBAQEBAQEBAQEBAQEBAQEAAAAAAAAAAAAAAAAAAAEBAQEBAQEBAQEBAQ==" - }, - "palette" : { - "originalArgb8888" : [ -265674 ], - "convertedRgb565" : [ -122 ] } }, "diagnostics" : [ ] @@ -726,14 +726,14 @@ "last_modified" : 1774359772454, "fingerprint" : "eeb7cc665386299403b7be1c272375d5077f3647c587f8033aa8c9275f840562", "metadata" : { + "palette" : { + "originalArgb8888" : [ -265674 ], + "convertedRgb565" : [ -122 ] + }, "tile" : { "width" : 32, "height" : 32, "paletteIndices" : "AQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAAAAAAAAAAABAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEAAAAAAAAAAAEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQAAAAAAAAAAAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAAAAAAAAAAABAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEAAAAAAAAAAAEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQAAAAAAAAAAAQEBAQEBAQEBAQEBAAAAAAAAAAAAAAAAAAAAAAAAAAABAQEBAQEBAQEBAQEAAAAAAAAAAAAAAAAAAAAAAAAAAAEBAQEBAQEBAQEBAQAAAAAAAAAAAAAAAAAAAAAAAAAAAQEBAQEBAQEBAQEBAAAAAAAAAAAAAAAAAAAAAAAAAAABAQEBAQEBAQEBAQEAAAAAAAAAAAAAAAAAAAAAAAAAAAEBAQEBAQEBAQEBAQAAAAAAAAAAAAAAAAAAAAAAAAAAAQEBAQEBAQEBAQEBAAAAAAAAAAAAAAAAAAAAAAAAAAABAQEBAQEBAQEBAQEAAAAAAAAAAAAAAAAAAAAAAAAAAAEBAQEBAQEBAQEBAQAAAAAAAAAAAAAAAAAAAQEBAQEBAQEBAQEBAQEBAQEBAAAAAAAAAAAAAAAAAAABAQEBAQEBAQEBAQEBAQEBAQEAAAAAAAAAAAAAAAAAAAEBAQEBAQEBAQEBAQEBAQEBAQAAAAAAAAAAAAAAAAAAAQEBAQEBAQEBAQEBAAAAAAAAAAAAAAAAAAAAAAAAAAABAQEBAQEBAQEBAQEAAAAAAAAAAAAAAAAAAAAAAAAAAAEBAQEBAQEBAQEBAQAAAAAAAAAAAAAAAAAAAQEBAQEBAQEBAQEBAQEBAQEBAAAAAAAAAAAAAAAAAAABAQEBAQEBAQEBAQEBAQEBAQEAAAAAAAAAAAAAAAAAAAEBAQEBAQEBAQEBAQEBAQEBAQAAAAAAAAAAAAAAAAAAAQEBAQEBAQEBAQEBAQEBAQEBAAAAAAAAAAAAAAAAAAABAQEBAQEBAQEBAQEBAQEBAQEAAAAAAAAAAAAAAAAAAAEBAQEBAQEBAQEBAQ==" - }, - "palette" : { - "originalArgb8888" : [ -265674 ], - "convertedRgb565" : [ -122 ] } }, "diagnostics" : [ ] @@ -744,14 +744,14 @@ "last_modified" : 1774359772455, "fingerprint" : "eeb7cc665386299403b7be1c272375d5077f3647c587f8033aa8c9275f840562", "metadata" : { + "palette" : { + "originalArgb8888" : [ -265674 ], + "convertedRgb565" : [ -122 ] + }, "tile" : { "width" : 32, "height" : 32, "paletteIndices" : "AQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAAAAAAAAAAABAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEAAAAAAAAAAAEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQAAAAAAAAAAAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAAAAAAAAAAABAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEAAAAAAAAAAAEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQAAAAAAAAAAAQEBAQEBAQEBAQEBAAAAAAAAAAAAAAAAAAAAAAAAAAABAQEBAQEBAQEBAQEAAAAAAAAAAAAAAAAAAAAAAAAAAAEBAQEBAQEBAQEBAQAAAAAAAAAAAAAAAAAAAAAAAAAAAQEBAQEBAQEBAQEBAAAAAAAAAAAAAAAAAAAAAAAAAAABAQEBAQEBAQEBAQEAAAAAAAAAAAAAAAAAAAAAAAAAAAEBAQEBAQEBAQEBAQAAAAAAAAAAAAAAAAAAAAAAAAAAAQEBAQEBAQEBAQEBAAAAAAAAAAAAAAAAAAAAAAAAAAABAQEBAQEBAQEBAQEAAAAAAAAAAAAAAAAAAAAAAAAAAAEBAQEBAQEBAQEBAQAAAAAAAAAAAAAAAAAAAQEBAQEBAQEBAQEBAQEBAQEBAAAAAAAAAAAAAAAAAAABAQEBAQEBAQEBAQEBAQEBAQEAAAAAAAAAAAAAAAAAAAEBAQEBAQEBAQEBAQEBAQEBAQAAAAAAAAAAAAAAAAAAAQEBAQEBAQEBAQEBAAAAAAAAAAAAAAAAAAAAAAAAAAABAQEBAQEBAQEBAQEAAAAAAAAAAAAAAAAAAAAAAAAAAAEBAQEBAQEBAQEBAQAAAAAAAAAAAAAAAAAAAQEBAQEBAQEBAQEBAQEBAQEBAAAAAAAAAAAAAAAAAAABAQEBAQEBAQEBAQEBAQEBAQEAAAAAAAAAAAAAAAAAAAEBAQEBAQEBAQEBAQEBAQEBAQAAAAAAAAAAAAAAAAAAAQEBAQEBAQEBAQEBAQEBAQEBAAAAAAAAAAAAAAAAAAABAQEBAQEBAQEBAQEBAQEBAQEAAAAAAAAAAAAAAAAAAAEBAQEBAQEBAQEBAQ==" - }, - "palette" : { - "originalArgb8888" : [ -265674 ], - "convertedRgb565" : [ -122 ] } }, "diagnostics" : [ ] @@ -762,14 +762,14 @@ "last_modified" : 1774359772456, "fingerprint" : "eeb7cc665386299403b7be1c272375d5077f3647c587f8033aa8c9275f840562", "metadata" : { + "palette" : { + "originalArgb8888" : [ -265674 ], + "convertedRgb565" : [ -122 ] + }, "tile" : { "width" : 32, "height" : 32, "paletteIndices" : "AQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAAAAAAAAAAABAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEAAAAAAAAAAAEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQAAAAAAAAAAAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAAAAAAAAAAABAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEAAAAAAAAAAAEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQAAAAAAAAAAAQEBAQEBAQEBAQEBAAAAAAAAAAAAAAAAAAAAAAAAAAABAQEBAQEBAQEBAQEAAAAAAAAAAAAAAAAAAAAAAAAAAAEBAQEBAQEBAQEBAQAAAAAAAAAAAAAAAAAAAAAAAAAAAQEBAQEBAQEBAQEBAAAAAAAAAAAAAAAAAAAAAAAAAAABAQEBAQEBAQEBAQEAAAAAAAAAAAAAAAAAAAAAAAAAAAEBAQEBAQEBAQEBAQAAAAAAAAAAAAAAAAAAAAAAAAAAAQEBAQEBAQEBAQEBAAAAAAAAAAAAAAAAAAAAAAAAAAABAQEBAQEBAQEBAQEAAAAAAAAAAAAAAAAAAAAAAAAAAAEBAQEBAQEBAQEBAQAAAAAAAAAAAAAAAAAAAQEBAQEBAQEBAQEBAQEBAQEBAAAAAAAAAAAAAAAAAAABAQEBAQEBAQEBAQEBAQEBAQEAAAAAAAAAAAAAAAAAAAEBAQEBAQEBAQEBAQEBAQEBAQAAAAAAAAAAAAAAAAAAAQEBAQEBAQEBAQEBAAAAAAAAAAAAAAAAAAAAAAAAAAABAQEBAQEBAQEBAQEAAAAAAAAAAAAAAAAAAAAAAAAAAAEBAQEBAQEBAQEBAQAAAAAAAAAAAAAAAAAAAQEBAQEBAQEBAQEBAQEBAQEBAAAAAAAAAAAAAAAAAAABAQEBAQEBAQEBAQEBAQEBAQEAAAAAAAAAAAAAAAAAAAEBAQEBAQEBAQEBAQEBAQEBAQAAAAAAAAAAAAAAAAAAAQEBAQEBAQEBAQEBAQEBAQEBAAAAAAAAAAAAAAAAAAABAQEBAQEBAQEBAQEBAQEBAQEAAAAAAAAAAAAAAAAAAAEBAQEBAQEBAQEBAQ==" - }, - "palette" : { - "originalArgb8888" : [ -265674 ], - "convertedRgb565" : [ -122 ] } }, "diagnostics" : [ ] @@ -780,14 +780,14 @@ "last_modified" : 1774359772458, "fingerprint" : "eeb7cc665386299403b7be1c272375d5077f3647c587f8033aa8c9275f840562", "metadata" : { + "palette" : { + "originalArgb8888" : [ -265674 ], + "convertedRgb565" : [ -122 ] + }, "tile" : { "width" : 32, "height" : 32, "paletteIndices" : "AQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAAAAAAAAAAABAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEAAAAAAAAAAAEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQAAAAAAAAAAAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAAAAAAAAAAABAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEAAAAAAAAAAAEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQAAAAAAAAAAAQEBAQEBAQEBAQEBAAAAAAAAAAAAAAAAAAAAAAAAAAABAQEBAQEBAQEBAQEAAAAAAAAAAAAAAAAAAAAAAAAAAAEBAQEBAQEBAQEBAQAAAAAAAAAAAAAAAAAAAAAAAAAAAQEBAQEBAQEBAQEBAAAAAAAAAAAAAAAAAAAAAAAAAAABAQEBAQEBAQEBAQEAAAAAAAAAAAAAAAAAAAAAAAAAAAEBAQEBAQEBAQEBAQAAAAAAAAAAAAAAAAAAAAAAAAAAAQEBAQEBAQEBAQEBAAAAAAAAAAAAAAAAAAAAAAAAAAABAQEBAQEBAQEBAQEAAAAAAAAAAAAAAAAAAAAAAAAAAAEBAQEBAQEBAQEBAQAAAAAAAAAAAAAAAAAAAQEBAQEBAQEBAQEBAQEBAQEBAAAAAAAAAAAAAAAAAAABAQEBAQEBAQEBAQEBAQEBAQEAAAAAAAAAAAAAAAAAAAEBAQEBAQEBAQEBAQEBAQEBAQAAAAAAAAAAAAAAAAAAAQEBAQEBAQEBAQEBAAAAAAAAAAAAAAAAAAAAAAAAAAABAQEBAQEBAQEBAQEAAAAAAAAAAAAAAAAAAAAAAAAAAAEBAQEBAQEBAQEBAQAAAAAAAAAAAAAAAAAAAQEBAQEBAQEBAQEBAQEBAQEBAAAAAAAAAAAAAAAAAAABAQEBAQEBAQEBAQEBAQEBAQEAAAAAAAAAAAAAAAAAAAEBAQEBAQEBAQEBAQEBAQEBAQAAAAAAAAAAAAAAAAAAAQEBAQEBAQEBAQEBAQEBAQEBAAAAAAAAAAAAAAAAAAABAQEBAQEBAQEBAQEBAQEBAQEAAAAAAAAAAAAAAAAAAAEBAQEBAQEBAQEBAQ==" - }, - "palette" : { - "originalArgb8888" : [ -265674 ], - "convertedRgb565" : [ -122 ] } }, "diagnostics" : [ ] @@ -798,14 +798,14 @@ "last_modified" : 1774359772459, "fingerprint" : "eeb7cc665386299403b7be1c272375d5077f3647c587f8033aa8c9275f840562", "metadata" : { + "palette" : { + "originalArgb8888" : [ -265674 ], + "convertedRgb565" : [ -122 ] + }, "tile" : { "width" : 32, "height" : 32, "paletteIndices" : "AQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAAAAAAAAAAABAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEAAAAAAAAAAAEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQAAAAAAAAAAAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAAAAAAAAAAABAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEAAAAAAAAAAAEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQAAAAAAAAAAAQEBAQEBAQEBAQEBAAAAAAAAAAAAAAAAAAAAAAAAAAABAQEBAQEBAQEBAQEAAAAAAAAAAAAAAAAAAAAAAAAAAAEBAQEBAQEBAQEBAQAAAAAAAAAAAAAAAAAAAAAAAAAAAQEBAQEBAQEBAQEBAAAAAAAAAAAAAAAAAAAAAAAAAAABAQEBAQEBAQEBAQEAAAAAAAAAAAAAAAAAAAAAAAAAAAEBAQEBAQEBAQEBAQAAAAAAAAAAAAAAAAAAAAAAAAAAAQEBAQEBAQEBAQEBAAAAAAAAAAAAAAAAAAAAAAAAAAABAQEBAQEBAQEBAQEAAAAAAAAAAAAAAAAAAAAAAAAAAAEBAQEBAQEBAQEBAQAAAAAAAAAAAAAAAAAAAQEBAQEBAQEBAQEBAQEBAQEBAAAAAAAAAAAAAAAAAAABAQEBAQEBAQEBAQEBAQEBAQEAAAAAAAAAAAAAAAAAAAEBAQEBAQEBAQEBAQEBAQEBAQAAAAAAAAAAAAAAAAAAAQEBAQEBAQEBAQEBAAAAAAAAAAAAAAAAAAAAAAAAAAABAQEBAQEBAQEBAQEAAAAAAAAAAAAAAAAAAAAAAAAAAAEBAQEBAQEBAQEBAQAAAAAAAAAAAAAAAAAAAQEBAQEBAQEBAQEBAQEBAQEBAAAAAAAAAAAAAAAAAAABAQEBAQEBAQEBAQEBAQEBAQEAAAAAAAAAAAAAAAAAAAEBAQEBAQEBAQEBAQEBAQEBAQAAAAAAAAAAAAAAAAAAAQEBAQEBAQEBAQEBAQEBAQEBAAAAAAAAAAAAAAAAAAABAQEBAQEBAQEBAQEBAQEBAQEAAAAAAAAAAAAAAAAAAAEBAQEBAQEBAQEBAQ==" - }, - "palette" : { - "originalArgb8888" : [ -265674 ], - "convertedRgb565" : [ -122 ] } }, "diagnostics" : [ ] @@ -816,14 +816,14 @@ "last_modified" : 1774359772460, "fingerprint" : "eeb7cc665386299403b7be1c272375d5077f3647c587f8033aa8c9275f840562", "metadata" : { + "palette" : { + "originalArgb8888" : [ -265674 ], + "convertedRgb565" : [ -122 ] + }, "tile" : { "width" : 32, "height" : 32, "paletteIndices" : "AQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAAAAAAAAAAABAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEAAAAAAAAAAAEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQAAAAAAAAAAAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAAAAAAAAAAABAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEAAAAAAAAAAAEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQAAAAAAAAAAAQEBAQEBAQEBAQEBAAAAAAAAAAAAAAAAAAAAAAAAAAABAQEBAQEBAQEBAQEAAAAAAAAAAAAAAAAAAAAAAAAAAAEBAQEBAQEBAQEBAQAAAAAAAAAAAAAAAAAAAAAAAAAAAQEBAQEBAQEBAQEBAAAAAAAAAAAAAAAAAAAAAAAAAAABAQEBAQEBAQEBAQEAAAAAAAAAAAAAAAAAAAAAAAAAAAEBAQEBAQEBAQEBAQAAAAAAAAAAAAAAAAAAAAAAAAAAAQEBAQEBAQEBAQEBAAAAAAAAAAAAAAAAAAAAAAAAAAABAQEBAQEBAQEBAQEAAAAAAAAAAAAAAAAAAAAAAAAAAAEBAQEBAQEBAQEBAQAAAAAAAAAAAAAAAAAAAQEBAQEBAQEBAQEBAQEBAQEBAAAAAAAAAAAAAAAAAAABAQEBAQEBAQEBAQEBAQEBAQEAAAAAAAAAAAAAAAAAAAEBAQEBAQEBAQEBAQEBAQEBAQAAAAAAAAAAAAAAAAAAAQEBAQEBAQEBAQEBAAAAAAAAAAAAAAAAAAAAAAAAAAABAQEBAQEBAQEBAQEAAAAAAAAAAAAAAAAAAAAAAAAAAAEBAQEBAQEBAQEBAQAAAAAAAAAAAAAAAAAAAQEBAQEBAQEBAQEBAQEBAQEBAAAAAAAAAAAAAAAAAAABAQEBAQEBAQEBAQEBAQEBAQEAAAAAAAAAAAAAAAAAAAEBAQEBAQEBAQEBAQEBAQEBAQAAAAAAAAAAAAAAAAAAAQEBAQEBAQEBAQEBAQEBAQEBAAAAAAAAAAAAAAAAAAABAQEBAQEBAQEBAQEBAQEBAQEAAAAAAAAAAAAAAAAAAAEBAQEBAQEBAQEBAQ==" - }, - "palette" : { - "originalArgb8888" : [ -265674 ], - "convertedRgb565" : [ -122 ] } }, "diagnostics" : [ ] @@ -834,14 +834,14 @@ "last_modified" : 1774359772461, "fingerprint" : "eeb7cc665386299403b7be1c272375d5077f3647c587f8033aa8c9275f840562", "metadata" : { + "palette" : { + "originalArgb8888" : [ -265674 ], + "convertedRgb565" : [ -122 ] + }, "tile" : { "width" : 32, "height" : 32, "paletteIndices" : "AQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAAAAAAAAAAABAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEAAAAAAAAAAAEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQAAAAAAAAAAAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAAAAAAAAAAABAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEAAAAAAAAAAAEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQAAAAAAAAAAAQEBAQEBAQEBAQEBAAAAAAAAAAAAAAAAAAAAAAAAAAABAQEBAQEBAQEBAQEAAAAAAAAAAAAAAAAAAAAAAAAAAAEBAQEBAQEBAQEBAQAAAAAAAAAAAAAAAAAAAAAAAAAAAQEBAQEBAQEBAQEBAAAAAAAAAAAAAAAAAAAAAAAAAAABAQEBAQEBAQEBAQEAAAAAAAAAAAAAAAAAAAAAAAAAAAEBAQEBAQEBAQEBAQAAAAAAAAAAAAAAAAAAAAAAAAAAAQEBAQEBAQEBAQEBAAAAAAAAAAAAAAAAAAAAAAAAAAABAQEBAQEBAQEBAQEAAAAAAAAAAAAAAAAAAAAAAAAAAAEBAQEBAQEBAQEBAQAAAAAAAAAAAAAAAAAAAQEBAQEBAQEBAQEBAQEBAQEBAAAAAAAAAAAAAAAAAAABAQEBAQEBAQEBAQEBAQEBAQEAAAAAAAAAAAAAAAAAAAEBAQEBAQEBAQEBAQEBAQEBAQAAAAAAAAAAAAAAAAAAAQEBAQEBAQEBAQEBAAAAAAAAAAAAAAAAAAAAAAAAAAABAQEBAQEBAQEBAQEAAAAAAAAAAAAAAAAAAAAAAAAAAAEBAQEBAQEBAQEBAQAAAAAAAAAAAAAAAAAAAQEBAQEBAQEBAQEBAQEBAQEBAAAAAAAAAAAAAAAAAAABAQEBAQEBAQEBAQEBAQEBAQEAAAAAAAAAAAAAAAAAAAEBAQEBAQEBAQEBAQEBAQEBAQAAAAAAAAAAAAAAAAAAAQEBAQEBAQEBAQEBAQEBAQEBAAAAAAAAAAAAAAAAAAABAQEBAQEBAQEBAQEBAQEBAQEAAAAAAAAAAAAAAAAAAAEBAQEBAQEBAQEBAQ==" - }, - "palette" : { - "originalArgb8888" : [ -265674 ], - "convertedRgb565" : [ -122 ] } }, "diagnostics" : [ ] @@ -852,14 +852,14 @@ "last_modified" : 1774359772463, "fingerprint" : "eeb7cc665386299403b7be1c272375d5077f3647c587f8033aa8c9275f840562", "metadata" : { + "palette" : { + "originalArgb8888" : [ -265674 ], + "convertedRgb565" : [ -122 ] + }, "tile" : { "width" : 32, "height" : 32, "paletteIndices" : "AQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAAAAAAAAAAABAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEAAAAAAAAAAAEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQAAAAAAAAAAAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAAAAAAAAAAABAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEAAAAAAAAAAAEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQAAAAAAAAAAAQEBAQEBAQEBAQEBAAAAAAAAAAAAAAAAAAAAAAAAAAABAQEBAQEBAQEBAQEAAAAAAAAAAAAAAAAAAAAAAAAAAAEBAQEBAQEBAQEBAQAAAAAAAAAAAAAAAAAAAAAAAAAAAQEBAQEBAQEBAQEBAAAAAAAAAAAAAAAAAAAAAAAAAAABAQEBAQEBAQEBAQEAAAAAAAAAAAAAAAAAAAAAAAAAAAEBAQEBAQEBAQEBAQAAAAAAAAAAAAAAAAAAAAAAAAAAAQEBAQEBAQEBAQEBAAAAAAAAAAAAAAAAAAAAAAAAAAABAQEBAQEBAQEBAQEAAAAAAAAAAAAAAAAAAAAAAAAAAAEBAQEBAQEBAQEBAQAAAAAAAAAAAAAAAAAAAQEBAQEBAQEBAQEBAQEBAQEBAAAAAAAAAAAAAAAAAAABAQEBAQEBAQEBAQEBAQEBAQEAAAAAAAAAAAAAAAAAAAEBAQEBAQEBAQEBAQEBAQEBAQAAAAAAAAAAAAAAAAAAAQEBAQEBAQEBAQEBAAAAAAAAAAAAAAAAAAAAAAAAAAABAQEBAQEBAQEBAQEAAAAAAAAAAAAAAAAAAAAAAAAAAAEBAQEBAQEBAQEBAQAAAAAAAAAAAAAAAAAAAQEBAQEBAQEBAQEBAQEBAQEBAAAAAAAAAAAAAAAAAAABAQEBAQEBAQEBAQEBAQEBAQEAAAAAAAAAAAAAAAAAAAEBAQEBAQEBAQEBAQEBAQEBAQAAAAAAAAAAAAAAAAAAAQEBAQEBAQEBAQEBAQEBAQEBAAAAAAAAAAAAAAAAAAABAQEBAQEBAQEBAQEBAQEBAQEAAAAAAAAAAAAAAAAAAAEBAQEBAQEBAQEBAQ==" - }, - "palette" : { - "originalArgb8888" : [ -265674 ], - "convertedRgb565" : [ -122 ] } }, "diagnostics" : [ ] @@ -870,14 +870,14 @@ "last_modified" : 1774359772464, "fingerprint" : "eeb7cc665386299403b7be1c272375d5077f3647c587f8033aa8c9275f840562", "metadata" : { + "palette" : { + "originalArgb8888" : [ -265674 ], + "convertedRgb565" : [ -122 ] + }, "tile" : { "width" : 32, "height" : 32, "paletteIndices" : "AQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAAAAAAAAAAABAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEAAAAAAAAAAAEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQAAAAAAAAAAAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAAAAAAAAAAABAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEAAAAAAAAAAAEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQAAAAAAAAAAAQEBAQEBAQEBAQEBAAAAAAAAAAAAAAAAAAAAAAAAAAABAQEBAQEBAQEBAQEAAAAAAAAAAAAAAAAAAAAAAAAAAAEBAQEBAQEBAQEBAQAAAAAAAAAAAAAAAAAAAAAAAAAAAQEBAQEBAQEBAQEBAAAAAAAAAAAAAAAAAAAAAAAAAAABAQEBAQEBAQEBAQEAAAAAAAAAAAAAAAAAAAAAAAAAAAEBAQEBAQEBAQEBAQAAAAAAAAAAAAAAAAAAAAAAAAAAAQEBAQEBAQEBAQEBAAAAAAAAAAAAAAAAAAAAAAAAAAABAQEBAQEBAQEBAQEAAAAAAAAAAAAAAAAAAAAAAAAAAAEBAQEBAQEBAQEBAQAAAAAAAAAAAAAAAAAAAQEBAQEBAQEBAQEBAQEBAQEBAAAAAAAAAAAAAAAAAAABAQEBAQEBAQEBAQEBAQEBAQEAAAAAAAAAAAAAAAAAAAEBAQEBAQEBAQEBAQEBAQEBAQAAAAAAAAAAAAAAAAAAAQEBAQEBAQEBAQEBAAAAAAAAAAAAAAAAAAAAAAAAAAABAQEBAQEBAQEBAQEAAAAAAAAAAAAAAAAAAAAAAAAAAAEBAQEBAQEBAQEBAQAAAAAAAAAAAAAAAAAAAQEBAQEBAQEBAQEBAQEBAQEBAAAAAAAAAAAAAAAAAAABAQEBAQEBAQEBAQEBAQEBAQEAAAAAAAAAAAAAAAAAAAEBAQEBAQEBAQEBAQEBAQEBAQAAAAAAAAAAAAAAAAAAAQEBAQEBAQEBAQEBAQEBAQEBAAAAAAAAAAAAAAAAAAABAQEBAQEBAQEBAQEBAQEBAQEAAAAAAAAAAAAAAAAAAAEBAQEBAQEBAQEBAQ==" - }, - "palette" : { - "originalArgb8888" : [ -265674 ], - "convertedRgb565" : [ -122 ] } }, "diagnostics" : [ ] @@ -888,14 +888,14 @@ "last_modified" : 1774359772465, "fingerprint" : "eeb7cc665386299403b7be1c272375d5077f3647c587f8033aa8c9275f840562", "metadata" : { + "palette" : { + "originalArgb8888" : [ -265674 ], + "convertedRgb565" : [ -122 ] + }, "tile" : { "width" : 32, "height" : 32, "paletteIndices" : "AQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAAAAAAAAAAABAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEAAAAAAAAAAAEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQAAAAAAAAAAAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAAAAAAAAAAABAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEAAAAAAAAAAAEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQAAAAAAAAAAAQEBAQEBAQEBAQEBAAAAAAAAAAAAAAAAAAAAAAAAAAABAQEBAQEBAQEBAQEAAAAAAAAAAAAAAAAAAAAAAAAAAAEBAQEBAQEBAQEBAQAAAAAAAAAAAAAAAAAAAAAAAAAAAQEBAQEBAQEBAQEBAAAAAAAAAAAAAAAAAAAAAAAAAAABAQEBAQEBAQEBAQEAAAAAAAAAAAAAAAAAAAAAAAAAAAEBAQEBAQEBAQEBAQAAAAAAAAAAAAAAAAAAAAAAAAAAAQEBAQEBAQEBAQEBAAAAAAAAAAAAAAAAAAAAAAAAAAABAQEBAQEBAQEBAQEAAAAAAAAAAAAAAAAAAAAAAAAAAAEBAQEBAQEBAQEBAQAAAAAAAAAAAAAAAAAAAQEBAQEBAQEBAQEBAQEBAQEBAAAAAAAAAAAAAAAAAAABAQEBAQEBAQEBAQEBAQEBAQEAAAAAAAAAAAAAAAAAAAEBAQEBAQEBAQEBAQEBAQEBAQAAAAAAAAAAAAAAAAAAAQEBAQEBAQEBAQEBAAAAAAAAAAAAAAAAAAAAAAAAAAABAQEBAQEBAQEBAQEAAAAAAAAAAAAAAAAAAAAAAAAAAAEBAQEBAQEBAQEBAQAAAAAAAAAAAAAAAAAAAQEBAQEBAQEBAQEBAQEBAQEBAAAAAAAAAAAAAAAAAAABAQEBAQEBAQEBAQEBAQEBAQEAAAAAAAAAAAAAAAAAAAEBAQEBAQEBAQEBAQEBAQEBAQAAAAAAAAAAAAAAAAAAAQEBAQEBAQEBAQEBAQEBAQEBAAAAAAAAAAAAAAAAAAABAQEBAQEBAQEBAQEBAQEBAQEAAAAAAAAAAAAAAAAAAAEBAQEBAQEBAQEBAQ==" - }, - "palette" : { - "originalArgb8888" : [ -265674 ], - "convertedRgb565" : [ -122 ] } }, "diagnostics" : [ ] @@ -906,14 +906,14 @@ "last_modified" : 1774359772467, "fingerprint" : "eeb7cc665386299403b7be1c272375d5077f3647c587f8033aa8c9275f840562", "metadata" : { + "palette" : { + "originalArgb8888" : [ -265674 ], + "convertedRgb565" : [ -122 ] + }, "tile" : { "width" : 32, "height" : 32, "paletteIndices" : "AQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAAAAAAAAAAABAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEAAAAAAAAAAAEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQAAAAAAAAAAAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAAAAAAAAAAABAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEAAAAAAAAAAAEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQAAAAAAAAAAAQEBAQEBAQEBAQEBAAAAAAAAAAAAAAAAAAAAAAAAAAABAQEBAQEBAQEBAQEAAAAAAAAAAAAAAAAAAAAAAAAAAAEBAQEBAQEBAQEBAQAAAAAAAAAAAAAAAAAAAAAAAAAAAQEBAQEBAQEBAQEBAAAAAAAAAAAAAAAAAAAAAAAAAAABAQEBAQEBAQEBAQEAAAAAAAAAAAAAAAAAAAAAAAAAAAEBAQEBAQEBAQEBAQAAAAAAAAAAAAAAAAAAAAAAAAAAAQEBAQEBAQEBAQEBAAAAAAAAAAAAAAAAAAAAAAAAAAABAQEBAQEBAQEBAQEAAAAAAAAAAAAAAAAAAAAAAAAAAAEBAQEBAQEBAQEBAQAAAAAAAAAAAAAAAAAAAQEBAQEBAQEBAQEBAQEBAQEBAAAAAAAAAAAAAAAAAAABAQEBAQEBAQEBAQEBAQEBAQEAAAAAAAAAAAAAAAAAAAEBAQEBAQEBAQEBAQEBAQEBAQAAAAAAAAAAAAAAAAAAAQEBAQEBAQEBAQEBAAAAAAAAAAAAAAAAAAAAAAAAAAABAQEBAQEBAQEBAQEAAAAAAAAAAAAAAAAAAAAAAAAAAAEBAQEBAQEBAQEBAQAAAAAAAAAAAAAAAAAAAQEBAQEBAQEBAQEBAQEBAQEBAAAAAAAAAAAAAAAAAAABAQEBAQEBAQEBAQEBAQEBAQEAAAAAAAAAAAAAAAAAAAEBAQEBAQEBAQEBAQEBAQEBAQAAAAAAAAAAAAAAAAAAAQEBAQEBAQEBAQEBAQEBAQEBAAAAAAAAAAAAAAAAAAABAQEBAQEBAQEBAQEBAQEBAQEAAAAAAAAAAAAAAAAAAAEBAQEBAQEBAQEBAQ==" - }, - "palette" : { - "originalArgb8888" : [ -265674 ], - "convertedRgb565" : [ -122 ] } }, "diagnostics" : [ ] @@ -924,14 +924,14 @@ "last_modified" : 1774359772468, "fingerprint" : "eeb7cc665386299403b7be1c272375d5077f3647c587f8033aa8c9275f840562", "metadata" : { + "palette" : { + "originalArgb8888" : [ -265674 ], + "convertedRgb565" : [ -122 ] + }, "tile" : { "width" : 32, "height" : 32, "paletteIndices" : "AQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAAAAAAAAAAABAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEAAAAAAAAAAAEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQAAAAAAAAAAAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAAAAAAAAAAABAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEAAAAAAAAAAAEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQAAAAAAAAAAAQEBAQEBAQEBAQEBAAAAAAAAAAAAAAAAAAAAAAAAAAABAQEBAQEBAQEBAQEAAAAAAAAAAAAAAAAAAAAAAAAAAAEBAQEBAQEBAQEBAQAAAAAAAAAAAAAAAAAAAAAAAAAAAQEBAQEBAQEBAQEBAAAAAAAAAAAAAAAAAAAAAAAAAAABAQEBAQEBAQEBAQEAAAAAAAAAAAAAAAAAAAAAAAAAAAEBAQEBAQEBAQEBAQAAAAAAAAAAAAAAAAAAAAAAAAAAAQEBAQEBAQEBAQEBAAAAAAAAAAAAAAAAAAAAAAAAAAABAQEBAQEBAQEBAQEAAAAAAAAAAAAAAAAAAAAAAAAAAAEBAQEBAQEBAQEBAQAAAAAAAAAAAAAAAAAAAQEBAQEBAQEBAQEBAQEBAQEBAAAAAAAAAAAAAAAAAAABAQEBAQEBAQEBAQEBAQEBAQEAAAAAAAAAAAAAAAAAAAEBAQEBAQEBAQEBAQEBAQEBAQAAAAAAAAAAAAAAAAAAAQEBAQEBAQEBAQEBAAAAAAAAAAAAAAAAAAAAAAAAAAABAQEBAQEBAQEBAQEAAAAAAAAAAAAAAAAAAAAAAAAAAAEBAQEBAQEBAQEBAQAAAAAAAAAAAAAAAAAAAQEBAQEBAQEBAQEBAQEBAQEBAAAAAAAAAAAAAAAAAAABAQEBAQEBAQEBAQEBAQEBAQEAAAAAAAAAAAAAAAAAAAEBAQEBAQEBAQEBAQEBAQEBAQAAAAAAAAAAAAAAAAAAAQEBAQEBAQEBAQEBAQEBAQEBAAAAAAAAAAAAAAAAAAABAQEBAQEBAQEBAQEBAQEBAQEAAAAAAAAAAAAAAAAAAAEBAQEBAQEBAQEBAQ==" - }, - "palette" : { - "originalArgb8888" : [ -265674 ], - "convertedRgb565" : [ -122 ] } }, "diagnostics" : [ ] @@ -942,14 +942,14 @@ "last_modified" : 1774359772470, "fingerprint" : "eeb7cc665386299403b7be1c272375d5077f3647c587f8033aa8c9275f840562", "metadata" : { + "palette" : { + "originalArgb8888" : [ -265674 ], + "convertedRgb565" : [ -122 ] + }, "tile" : { "width" : 32, "height" : 32, "paletteIndices" : "AQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAAAAAAAAAAABAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEAAAAAAAAAAAEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQAAAAAAAAAAAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAAAAAAAAAAABAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEAAAAAAAAAAAEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQAAAAAAAAAAAQEBAQEBAQEBAQEBAAAAAAAAAAAAAAAAAAAAAAAAAAABAQEBAQEBAQEBAQEAAAAAAAAAAAAAAAAAAAAAAAAAAAEBAQEBAQEBAQEBAQAAAAAAAAAAAAAAAAAAAAAAAAAAAQEBAQEBAQEBAQEBAAAAAAAAAAAAAAAAAAAAAAAAAAABAQEBAQEBAQEBAQEAAAAAAAAAAAAAAAAAAAAAAAAAAAEBAQEBAQEBAQEBAQAAAAAAAAAAAAAAAAAAAAAAAAAAAQEBAQEBAQEBAQEBAAAAAAAAAAAAAAAAAAAAAAAAAAABAQEBAQEBAQEBAQEAAAAAAAAAAAAAAAAAAAAAAAAAAAEBAQEBAQEBAQEBAQAAAAAAAAAAAAAAAAAAAQEBAQEBAQEBAQEBAQEBAQEBAAAAAAAAAAAAAAAAAAABAQEBAQEBAQEBAQEBAQEBAQEAAAAAAAAAAAAAAAAAAAEBAQEBAQEBAQEBAQEBAQEBAQAAAAAAAAAAAAAAAAAAAQEBAQEBAQEBAQEBAAAAAAAAAAAAAAAAAAAAAAAAAAABAQEBAQEBAQEBAQEAAAAAAAAAAAAAAAAAAAAAAAAAAAEBAQEBAQEBAQEBAQAAAAAAAAAAAAAAAAAAAQEBAQEBAQEBAQEBAQEBAQEBAAAAAAAAAAAAAAAAAAABAQEBAQEBAQEBAQEBAQEBAQEAAAAAAAAAAAAAAAAAAAEBAQEBAQEBAQEBAQEBAQEBAQAAAAAAAAAAAAAAAAAAAQEBAQEBAQEBAQEBAQEBAQEBAAAAAAAAAAAAAAAAAAABAQEBAQEBAQEBAQEBAQEBAQEAAAAAAAAAAAAAAAAAAAEBAQEBAQEBAQEBAQ==" - }, - "palette" : { - "originalArgb8888" : [ -265674 ], - "convertedRgb565" : [ -122 ] } }, "diagnostics" : [ ] @@ -960,14 +960,14 @@ "last_modified" : 1774359772474, "fingerprint" : "eeb7cc665386299403b7be1c272375d5077f3647c587f8033aa8c9275f840562", "metadata" : { + "palette" : { + "originalArgb8888" : [ -265674 ], + "convertedRgb565" : [ -122 ] + }, "tile" : { "width" : 32, "height" : 32, "paletteIndices" : "AQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAAAAAAAAAAABAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEAAAAAAAAAAAEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQAAAAAAAAAAAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAAAAAAAAAAABAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEAAAAAAAAAAAEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQAAAAAAAAAAAQEBAQEBAQEBAQEBAAAAAAAAAAAAAAAAAAAAAAAAAAABAQEBAQEBAQEBAQEAAAAAAAAAAAAAAAAAAAAAAAAAAAEBAQEBAQEBAQEBAQAAAAAAAAAAAAAAAAAAAAAAAAAAAQEBAQEBAQEBAQEBAAAAAAAAAAAAAAAAAAAAAAAAAAABAQEBAQEBAQEBAQEAAAAAAAAAAAAAAAAAAAAAAAAAAAEBAQEBAQEBAQEBAQAAAAAAAAAAAAAAAAAAAAAAAAAAAQEBAQEBAQEBAQEBAAAAAAAAAAAAAAAAAAAAAAAAAAABAQEBAQEBAQEBAQEAAAAAAAAAAAAAAAAAAAAAAAAAAAEBAQEBAQEBAQEBAQAAAAAAAAAAAAAAAAAAAQEBAQEBAQEBAQEBAQEBAQEBAAAAAAAAAAAAAAAAAAABAQEBAQEBAQEBAQEBAQEBAQEAAAAAAAAAAAAAAAAAAAEBAQEBAQEBAQEBAQEBAQEBAQAAAAAAAAAAAAAAAAAAAQEBAQEBAQEBAQEBAAAAAAAAAAAAAAAAAAAAAAAAAAABAQEBAQEBAQEBAQEAAAAAAAAAAAAAAAAAAAAAAAAAAAEBAQEBAQEBAQEBAQAAAAAAAAAAAAAAAAAAAQEBAQEBAQEBAQEBAQEBAQEBAAAAAAAAAAAAAAAAAAABAQEBAQEBAQEBAQEBAQEBAQEAAAAAAAAAAAAAAAAAAAEBAQEBAQEBAQEBAQEBAQEBAQAAAAAAAAAAAAAAAAAAAQEBAQEBAQEBAQEBAQEBAQEBAAAAAAAAAAAAAAAAAAABAQEBAQEBAQEBAQEBAQEBAQEAAAAAAAAAAAAAAAAAAAEBAQEBAQEBAQEBAQ==" - }, - "palette" : { - "originalArgb8888" : [ -265674 ], - "convertedRgb565" : [ -122 ] } }, "diagnostics" : [ ] @@ -978,14 +978,14 @@ "last_modified" : 1774359772476, "fingerprint" : "eeb7cc665386299403b7be1c272375d5077f3647c587f8033aa8c9275f840562", "metadata" : { + "palette" : { + "originalArgb8888" : [ -265674 ], + "convertedRgb565" : [ -122 ] + }, "tile" : { "width" : 32, "height" : 32, "paletteIndices" : "AQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAAAAAAAAAAABAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEAAAAAAAAAAAEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQAAAAAAAAAAAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAAAAAAAAAAABAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEAAAAAAAAAAAEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQAAAAAAAAAAAQEBAQEBAQEBAQEBAAAAAAAAAAAAAAAAAAAAAAAAAAABAQEBAQEBAQEBAQEAAAAAAAAAAAAAAAAAAAAAAAAAAAEBAQEBAQEBAQEBAQAAAAAAAAAAAAAAAAAAAAAAAAAAAQEBAQEBAQEBAQEBAAAAAAAAAAAAAAAAAAAAAAAAAAABAQEBAQEBAQEBAQEAAAAAAAAAAAAAAAAAAAAAAAAAAAEBAQEBAQEBAQEBAQAAAAAAAAAAAAAAAAAAAAAAAAAAAQEBAQEBAQEBAQEBAAAAAAAAAAAAAAAAAAAAAAAAAAABAQEBAQEBAQEBAQEAAAAAAAAAAAAAAAAAAAAAAAAAAAEBAQEBAQEBAQEBAQAAAAAAAAAAAAAAAAAAAQEBAQEBAQEBAQEBAQEBAQEBAAAAAAAAAAAAAAAAAAABAQEBAQEBAQEBAQEBAQEBAQEAAAAAAAAAAAAAAAAAAAEBAQEBAQEBAQEBAQEBAQEBAQAAAAAAAAAAAAAAAAAAAQEBAQEBAQEBAQEBAAAAAAAAAAAAAAAAAAAAAAAAAAABAQEBAQEBAQEBAQEAAAAAAAAAAAAAAAAAAAAAAAAAAAEBAQEBAQEBAQEBAQAAAAAAAAAAAAAAAAAAAQEBAQEBAQEBAQEBAQEBAQEBAAAAAAAAAAAAAAAAAAABAQEBAQEBAQEBAQEBAQEBAQEAAAAAAAAAAAAAAAAAAAEBAQEBAQEBAQEBAQEBAQEBAQAAAAAAAAAAAAAAAAAAAQEBAQEBAQEBAQEBAQEBAQEBAAAAAAAAAAAAAAAAAAABAQEBAQEBAQEBAQEBAQEBAQEAAAAAAAAAAAAAAAAAAAEBAQEBAQEBAQEBAQ==" - }, - "palette" : { - "originalArgb8888" : [ -265674 ], - "convertedRgb565" : [ -122 ] } }, "diagnostics" : [ ] @@ -996,14 +996,14 @@ "last_modified" : 1774359772478, "fingerprint" : "eeb7cc665386299403b7be1c272375d5077f3647c587f8033aa8c9275f840562", "metadata" : { + "palette" : { + "originalArgb8888" : [ -265674 ], + "convertedRgb565" : [ -122 ] + }, "tile" : { "width" : 32, "height" : 32, "paletteIndices" : "AQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAAAAAAAAAAABAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEAAAAAAAAAAAEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQAAAAAAAAAAAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAAAAAAAAAAABAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEAAAAAAAAAAAEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQAAAAAAAAAAAQEBAQEBAQEBAQEBAAAAAAAAAAAAAAAAAAAAAAAAAAABAQEBAQEBAQEBAQEAAAAAAAAAAAAAAAAAAAAAAAAAAAEBAQEBAQEBAQEBAQAAAAAAAAAAAAAAAAAAAAAAAAAAAQEBAQEBAQEBAQEBAAAAAAAAAAAAAAAAAAAAAAAAAAABAQEBAQEBAQEBAQEAAAAAAAAAAAAAAAAAAAAAAAAAAAEBAQEBAQEBAQEBAQAAAAAAAAAAAAAAAAAAAAAAAAAAAQEBAQEBAQEBAQEBAAAAAAAAAAAAAAAAAAAAAAAAAAABAQEBAQEBAQEBAQEAAAAAAAAAAAAAAAAAAAAAAAAAAAEBAQEBAQEBAQEBAQAAAAAAAAAAAAAAAAAAAQEBAQEBAQEBAQEBAQEBAQEBAAAAAAAAAAAAAAAAAAABAQEBAQEBAQEBAQEBAQEBAQEAAAAAAAAAAAAAAAAAAAEBAQEBAQEBAQEBAQEBAQEBAQAAAAAAAAAAAAAAAAAAAQEBAQEBAQEBAQEBAAAAAAAAAAAAAAAAAAAAAAAAAAABAQEBAQEBAQEBAQEAAAAAAAAAAAAAAAAAAAAAAAAAAAEBAQEBAQEBAQEBAQAAAAAAAAAAAAAAAAAAAQEBAQEBAQEBAQEBAQEBAQEBAAAAAAAAAAAAAAAAAAABAQEBAQEBAQEBAQEBAQEBAQEAAAAAAAAAAAAAAAAAAAEBAQEBAQEBAQEBAQEBAQEBAQAAAAAAAAAAAAAAAAAAAQEBAQEBAQEBAQEBAQEBAQEBAAAAAAAAAAAAAAAAAAABAQEBAQEBAQEBAQEBAQEBAQEAAAAAAAAAAAAAAAAAAAEBAQEBAQEBAQEBAQ==" - }, - "palette" : { - "originalArgb8888" : [ -265674 ], - "convertedRgb565" : [ -122 ] } }, "diagnostics" : [ ] @@ -1014,14 +1014,14 @@ "last_modified" : 1774359772479, "fingerprint" : "eeb7cc665386299403b7be1c272375d5077f3647c587f8033aa8c9275f840562", "metadata" : { + "palette" : { + "originalArgb8888" : [ -265674 ], + "convertedRgb565" : [ -122 ] + }, "tile" : { "width" : 32, "height" : 32, "paletteIndices" : "AQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAAAAAAAAAAABAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEAAAAAAAAAAAEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQAAAAAAAAAAAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAAAAAAAAAAABAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEAAAAAAAAAAAEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQAAAAAAAAAAAQEBAQEBAQEBAQEBAAAAAAAAAAAAAAAAAAAAAAAAAAABAQEBAQEBAQEBAQEAAAAAAAAAAAAAAAAAAAAAAAAAAAEBAQEBAQEBAQEBAQAAAAAAAAAAAAAAAAAAAAAAAAAAAQEBAQEBAQEBAQEBAAAAAAAAAAAAAAAAAAAAAAAAAAABAQEBAQEBAQEBAQEAAAAAAAAAAAAAAAAAAAAAAAAAAAEBAQEBAQEBAQEBAQAAAAAAAAAAAAAAAAAAAAAAAAAAAQEBAQEBAQEBAQEBAAAAAAAAAAAAAAAAAAAAAAAAAAABAQEBAQEBAQEBAQEAAAAAAAAAAAAAAAAAAAAAAAAAAAEBAQEBAQEBAQEBAQAAAAAAAAAAAAAAAAAAAQEBAQEBAQEBAQEBAQEBAQEBAAAAAAAAAAAAAAAAAAABAQEBAQEBAQEBAQEBAQEBAQEAAAAAAAAAAAAAAAAAAAEBAQEBAQEBAQEBAQEBAQEBAQAAAAAAAAAAAAAAAAAAAQEBAQEBAQEBAQEBAAAAAAAAAAAAAAAAAAAAAAAAAAABAQEBAQEBAQEBAQEAAAAAAAAAAAAAAAAAAAAAAAAAAAEBAQEBAQEBAQEBAQAAAAAAAAAAAAAAAAAAAQEBAQEBAQEBAQEBAQEBAQEBAAAAAAAAAAAAAAAAAAABAQEBAQEBAQEBAQEBAQEBAQEAAAAAAAAAAAAAAAAAAAEBAQEBAQEBAQEBAQEBAQEBAQAAAAAAAAAAAAAAAAAAAQEBAQEBAQEBAQEBAQEBAQEBAAAAAAAAAAAAAAAAAAABAQEBAQEBAQEBAQEBAQEBAQEAAAAAAAAAAAAAAAAAAAEBAQEBAQEBAQEBAQ==" - }, - "palette" : { - "originalArgb8888" : [ -265674 ], - "convertedRgb565" : [ -122 ] } }, "diagnostics" : [ ] @@ -1032,14 +1032,14 @@ "last_modified" : 1774359772481, "fingerprint" : "eeb7cc665386299403b7be1c272375d5077f3647c587f8033aa8c9275f840562", "metadata" : { + "palette" : { + "originalArgb8888" : [ -265674 ], + "convertedRgb565" : [ -122 ] + }, "tile" : { "width" : 32, "height" : 32, "paletteIndices" : "AQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAAAAAAAAAAABAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEAAAAAAAAAAAEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQAAAAAAAAAAAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAAAAAAAAAAABAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEAAAAAAAAAAAEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQAAAAAAAAAAAQEBAQEBAQEBAQEBAAAAAAAAAAAAAAAAAAAAAAAAAAABAQEBAQEBAQEBAQEAAAAAAAAAAAAAAAAAAAAAAAAAAAEBAQEBAQEBAQEBAQAAAAAAAAAAAAAAAAAAAAAAAAAAAQEBAQEBAQEBAQEBAAAAAAAAAAAAAAAAAAAAAAAAAAABAQEBAQEBAQEBAQEAAAAAAAAAAAAAAAAAAAAAAAAAAAEBAQEBAQEBAQEBAQAAAAAAAAAAAAAAAAAAAAAAAAAAAQEBAQEBAQEBAQEBAAAAAAAAAAAAAAAAAAAAAAAAAAABAQEBAQEBAQEBAQEAAAAAAAAAAAAAAAAAAAAAAAAAAAEBAQEBAQEBAQEBAQAAAAAAAAAAAAAAAAAAAQEBAQEBAQEBAQEBAQEBAQEBAAAAAAAAAAAAAAAAAAABAQEBAQEBAQEBAQEBAQEBAQEAAAAAAAAAAAAAAAAAAAEBAQEBAQEBAQEBAQEBAQEBAQAAAAAAAAAAAAAAAAAAAQEBAQEBAQEBAQEBAAAAAAAAAAAAAAAAAAAAAAAAAAABAQEBAQEBAQEBAQEAAAAAAAAAAAAAAAAAAAAAAAAAAAEBAQEBAQEBAQEBAQAAAAAAAAAAAAAAAAAAAQEBAQEBAQEBAQEBAQEBAQEBAAAAAAAAAAAAAAAAAAABAQEBAQEBAQEBAQEBAQEBAQEAAAAAAAAAAAAAAAAAAAEBAQEBAQEBAQEBAQEBAQEBAQAAAAAAAAAAAAAAAAAAAQEBAQEBAQEBAQEBAQEBAQEBAAAAAAAAAAAAAAAAAAABAQEBAQEBAQEBAQEBAQEBAQEAAAAAAAAAAAAAAAAAAAEBAQEBAQEBAQEBAQ==" - }, - "palette" : { - "originalArgb8888" : [ -265674 ], - "convertedRgb565" : [ -122 ] } }, "diagnostics" : [ ] @@ -1050,14 +1050,14 @@ "last_modified" : 1774359772482, "fingerprint" : "eeb7cc665386299403b7be1c272375d5077f3647c587f8033aa8c9275f840562", "metadata" : { + "palette" : { + "originalArgb8888" : [ -265674 ], + "convertedRgb565" : [ -122 ] + }, "tile" : { "width" : 32, "height" : 32, "paletteIndices" : "AQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAAAAAAAAAAABAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEAAAAAAAAAAAEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQAAAAAAAAAAAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAAAAAAAAAAABAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEAAAAAAAAAAAEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQAAAAAAAAAAAQEBAQEBAQEBAQEBAAAAAAAAAAAAAAAAAAAAAAAAAAABAQEBAQEBAQEBAQEAAAAAAAAAAAAAAAAAAAAAAAAAAAEBAQEBAQEBAQEBAQAAAAAAAAAAAAAAAAAAAAAAAAAAAQEBAQEBAQEBAQEBAAAAAAAAAAAAAAAAAAAAAAAAAAABAQEBAQEBAQEBAQEAAAAAAAAAAAAAAAAAAAAAAAAAAAEBAQEBAQEBAQEBAQAAAAAAAAAAAAAAAAAAAAAAAAAAAQEBAQEBAQEBAQEBAAAAAAAAAAAAAAAAAAAAAAAAAAABAQEBAQEBAQEBAQEAAAAAAAAAAAAAAAAAAAAAAAAAAAEBAQEBAQEBAQEBAQAAAAAAAAAAAAAAAAAAAQEBAQEBAQEBAQEBAQEBAQEBAAAAAAAAAAAAAAAAAAABAQEBAQEBAQEBAQEBAQEBAQEAAAAAAAAAAAAAAAAAAAEBAQEBAQEBAQEBAQEBAQEBAQAAAAAAAAAAAAAAAAAAAQEBAQEBAQEBAQEBAAAAAAAAAAAAAAAAAAAAAAAAAAABAQEBAQEBAQEBAQEAAAAAAAAAAAAAAAAAAAAAAAAAAAEBAQEBAQEBAQEBAQAAAAAAAAAAAAAAAAAAAQEBAQEBAQEBAQEBAQEBAQEBAAAAAAAAAAAAAAAAAAABAQEBAQEBAQEBAQEBAQEBAQEAAAAAAAAAAAAAAAAAAAEBAQEBAQEBAQEBAQEBAQEBAQAAAAAAAAAAAAAAAAAAAQEBAQEBAQEBAQEBAQEBAQEBAAAAAAAAAAAAAAAAAAABAQEBAQEBAQEBAQEBAQEBAQEAAAAAAAAAAAAAAAAAAAEBAQEBAQEBAQEBAQ==" - }, - "palette" : { - "originalArgb8888" : [ -265674 ], - "convertedRgb565" : [ -122 ] } }, "diagnostics" : [ ] @@ -1068,14 +1068,14 @@ "last_modified" : 1774359772483, "fingerprint" : "eeb7cc665386299403b7be1c272375d5077f3647c587f8033aa8c9275f840562", "metadata" : { + "palette" : { + "originalArgb8888" : [ -265674 ], + "convertedRgb565" : [ -122 ] + }, "tile" : { "width" : 32, "height" : 32, "paletteIndices" : "AQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAAAAAAAAAAABAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEAAAAAAAAAAAEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQAAAAAAAAAAAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAAAAAAAAAAABAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEAAAAAAAAAAAEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQAAAAAAAAAAAQEBAQEBAQEBAQEBAAAAAAAAAAAAAAAAAAAAAAAAAAABAQEBAQEBAQEBAQEAAAAAAAAAAAAAAAAAAAAAAAAAAAEBAQEBAQEBAQEBAQAAAAAAAAAAAAAAAAAAAAAAAAAAAQEBAQEBAQEBAQEBAAAAAAAAAAAAAAAAAAAAAAAAAAABAQEBAQEBAQEBAQEAAAAAAAAAAAAAAAAAAAAAAAAAAAEBAQEBAQEBAQEBAQAAAAAAAAAAAAAAAAAAAAAAAAAAAQEBAQEBAQEBAQEBAAAAAAAAAAAAAAAAAAAAAAAAAAABAQEBAQEBAQEBAQEAAAAAAAAAAAAAAAAAAAAAAAAAAAEBAQEBAQEBAQEBAQAAAAAAAAAAAAAAAAAAAQEBAQEBAQEBAQEBAQEBAQEBAAAAAAAAAAAAAAAAAAABAQEBAQEBAQEBAQEBAQEBAQEAAAAAAAAAAAAAAAAAAAEBAQEBAQEBAQEBAQEBAQEBAQAAAAAAAAAAAAAAAAAAAQEBAQEBAQEBAQEBAAAAAAAAAAAAAAAAAAAAAAAAAAABAQEBAQEBAQEBAQEAAAAAAAAAAAAAAAAAAAAAAAAAAAEBAQEBAQEBAQEBAQAAAAAAAAAAAAAAAAAAAQEBAQEBAQEBAQEBAQEBAQEBAAAAAAAAAAAAAAAAAAABAQEBAQEBAQEBAQEBAQEBAQEAAAAAAAAAAAAAAAAAAAEBAQEBAQEBAQEBAQEBAQEBAQAAAAAAAAAAAAAAAAAAAQEBAQEBAQEBAQEBAQEBAQEBAAAAAAAAAAAAAAAAAAABAQEBAQEBAQEBAQEBAQEBAQEAAAAAAAAAAAAAAAAAAAEBAQEBAQEBAQEBAQ==" - }, - "palette" : { - "originalArgb8888" : [ -265674 ], - "convertedRgb565" : [ -122 ] } }, "diagnostics" : [ ] @@ -1086,14 +1086,14 @@ "last_modified" : 1774359772484, "fingerprint" : "eeb7cc665386299403b7be1c272375d5077f3647c587f8033aa8c9275f840562", "metadata" : { + "palette" : { + "originalArgb8888" : [ -265674 ], + "convertedRgb565" : [ -122 ] + }, "tile" : { "width" : 32, "height" : 32, "paletteIndices" : "AQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAAAAAAAAAAABAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEAAAAAAAAAAAEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQAAAAAAAAAAAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAAAAAAAAAAABAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEAAAAAAAAAAAEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQAAAAAAAAAAAQEBAQEBAQEBAQEBAAAAAAAAAAAAAAAAAAAAAAAAAAABAQEBAQEBAQEBAQEAAAAAAAAAAAAAAAAAAAAAAAAAAAEBAQEBAQEBAQEBAQAAAAAAAAAAAAAAAAAAAAAAAAAAAQEBAQEBAQEBAQEBAAAAAAAAAAAAAAAAAAAAAAAAAAABAQEBAQEBAQEBAQEAAAAAAAAAAAAAAAAAAAAAAAAAAAEBAQEBAQEBAQEBAQAAAAAAAAAAAAAAAAAAAAAAAAAAAQEBAQEBAQEBAQEBAAAAAAAAAAAAAAAAAAAAAAAAAAABAQEBAQEBAQEBAQEAAAAAAAAAAAAAAAAAAAAAAAAAAAEBAQEBAQEBAQEBAQAAAAAAAAAAAAAAAAAAAQEBAQEBAQEBAQEBAQEBAQEBAAAAAAAAAAAAAAAAAAABAQEBAQEBAQEBAQEBAQEBAQEAAAAAAAAAAAAAAAAAAAEBAQEBAQEBAQEBAQEBAQEBAQAAAAAAAAAAAAAAAAAAAQEBAQEBAQEBAQEBAAAAAAAAAAAAAAAAAAAAAAAAAAABAQEBAQEBAQEBAQEAAAAAAAAAAAAAAAAAAAAAAAAAAAEBAQEBAQEBAQEBAQAAAAAAAAAAAAAAAAAAAQEBAQEBAQEBAQEBAQEBAQEBAAAAAAAAAAAAAAAAAAABAQEBAQEBAQEBAQEBAQEBAQEAAAAAAAAAAAAAAAAAAAEBAQEBAQEBAQEBAQEBAQEBAQAAAAAAAAAAAAAAAAAAAQEBAQEBAQEBAQEBAQEBAQEBAAAAAAAAAAAAAAAAAAABAQEBAQEBAQEBAQEBAQEBAQEAAAAAAAAAAAAAAAAAAAEBAQEBAQEBAQEBAQ==" - }, - "palette" : { - "originalArgb8888" : [ -265674 ], - "convertedRgb565" : [ -122 ] } }, "diagnostics" : [ ] @@ -1104,14 +1104,14 @@ "last_modified" : 1774359772485, "fingerprint" : "eeb7cc665386299403b7be1c272375d5077f3647c587f8033aa8c9275f840562", "metadata" : { + "palette" : { + "originalArgb8888" : [ -265674 ], + "convertedRgb565" : [ -122 ] + }, "tile" : { "width" : 32, "height" : 32, "paletteIndices" : "AQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAAAAAAAAAAABAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEAAAAAAAAAAAEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQAAAAAAAAAAAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAAAAAAAAAAABAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEAAAAAAAAAAAEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQAAAAAAAAAAAQEBAQEBAQEBAQEBAAAAAAAAAAAAAAAAAAAAAAAAAAABAQEBAQEBAQEBAQEAAAAAAAAAAAAAAAAAAAAAAAAAAAEBAQEBAQEBAQEBAQAAAAAAAAAAAAAAAAAAAAAAAAAAAQEBAQEBAQEBAQEBAAAAAAAAAAAAAAAAAAAAAAAAAAABAQEBAQEBAQEBAQEAAAAAAAAAAAAAAAAAAAAAAAAAAAEBAQEBAQEBAQEBAQAAAAAAAAAAAAAAAAAAAAAAAAAAAQEBAQEBAQEBAQEBAAAAAAAAAAAAAAAAAAAAAAAAAAABAQEBAQEBAQEBAQEAAAAAAAAAAAAAAAAAAAAAAAAAAAEBAQEBAQEBAQEBAQAAAAAAAAAAAAAAAAAAAQEBAQEBAQEBAQEBAQEBAQEBAAAAAAAAAAAAAAAAAAABAQEBAQEBAQEBAQEBAQEBAQEAAAAAAAAAAAAAAAAAAAEBAQEBAQEBAQEBAQEBAQEBAQAAAAAAAAAAAAAAAAAAAQEBAQEBAQEBAQEBAAAAAAAAAAAAAAAAAAAAAAAAAAABAQEBAQEBAQEBAQEAAAAAAAAAAAAAAAAAAAAAAAAAAAEBAQEBAQEBAQEBAQAAAAAAAAAAAAAAAAAAAQEBAQEBAQEBAQEBAQEBAQEBAAAAAAAAAAAAAAAAAAABAQEBAQEBAQEBAQEBAQEBAQEAAAAAAAAAAAAAAAAAAAEBAQEBAQEBAQEBAQEBAQEBAQAAAAAAAAAAAAAAAAAAAQEBAQEBAQEBAQEBAQEBAQEBAAAAAAAAAAAAAAAAAAABAQEBAQEBAQEBAQEBAQEBAQEAAAAAAAAAAAAAAAAAAAEBAQEBAQEBAQEBAQ==" - }, - "palette" : { - "originalArgb8888" : [ -265674 ], - "convertedRgb565" : [ -122 ] } }, "diagnostics" : [ ] @@ -1122,14 +1122,14 @@ "last_modified" : 1774359772487, "fingerprint" : "eeb7cc665386299403b7be1c272375d5077f3647c587f8033aa8c9275f840562", "metadata" : { + "palette" : { + "originalArgb8888" : [ -265674 ], + "convertedRgb565" : [ -122 ] + }, "tile" : { "width" : 32, "height" : 32, "paletteIndices" : "AQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAAAAAAAAAAABAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEAAAAAAAAAAAEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQAAAAAAAAAAAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAAAAAAAAAAABAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEAAAAAAAAAAAEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQAAAAAAAAAAAQEBAQEBAQEBAQEBAAAAAAAAAAAAAAAAAAAAAAAAAAABAQEBAQEBAQEBAQEAAAAAAAAAAAAAAAAAAAAAAAAAAAEBAQEBAQEBAQEBAQAAAAAAAAAAAAAAAAAAAAAAAAAAAQEBAQEBAQEBAQEBAAAAAAAAAAAAAAAAAAAAAAAAAAABAQEBAQEBAQEBAQEAAAAAAAAAAAAAAAAAAAAAAAAAAAEBAQEBAQEBAQEBAQAAAAAAAAAAAAAAAAAAAAAAAAAAAQEBAQEBAQEBAQEBAAAAAAAAAAAAAAAAAAAAAAAAAAABAQEBAQEBAQEBAQEAAAAAAAAAAAAAAAAAAAAAAAAAAAEBAQEBAQEBAQEBAQAAAAAAAAAAAAAAAAAAAQEBAQEBAQEBAQEBAQEBAQEBAAAAAAAAAAAAAAAAAAABAQEBAQEBAQEBAQEBAQEBAQEAAAAAAAAAAAAAAAAAAAEBAQEBAQEBAQEBAQEBAQEBAQAAAAAAAAAAAAAAAAAAAQEBAQEBAQEBAQEBAAAAAAAAAAAAAAAAAAAAAAAAAAABAQEBAQEBAQEBAQEAAAAAAAAAAAAAAAAAAAAAAAAAAAEBAQEBAQEBAQEBAQAAAAAAAAAAAAAAAAAAAQEBAQEBAQEBAQEBAQEBAQEBAAAAAAAAAAAAAAAAAAABAQEBAQEBAQEBAQEBAQEBAQEAAAAAAAAAAAAAAAAAAAEBAQEBAQEBAQEBAQEBAQEBAQAAAAAAAAAAAAAAAAAAAQEBAQEBAQEBAQEBAQEBAQEBAAAAAAAAAAAAAAAAAAABAQEBAQEBAQEBAQEBAQEBAQEAAAAAAAAAAAAAAAAAAAEBAQEBAQEBAQEBAQ==" - }, - "palette" : { - "originalArgb8888" : [ -265674 ], - "convertedRgb565" : [ -122 ] } }, "diagnostics" : [ ] @@ -1140,14 +1140,14 @@ "last_modified" : 1774359772488, "fingerprint" : "eeb7cc665386299403b7be1c272375d5077f3647c587f8033aa8c9275f840562", "metadata" : { + "palette" : { + "originalArgb8888" : [ -265674 ], + "convertedRgb565" : [ -122 ] + }, "tile" : { "width" : 32, "height" : 32, "paletteIndices" : "AQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAAAAAAAAAAABAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEAAAAAAAAAAAEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQAAAAAAAAAAAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAAAAAAAAAAABAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEAAAAAAAAAAAEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQAAAAAAAAAAAQEBAQEBAQEBAQEBAAAAAAAAAAAAAAAAAAAAAAAAAAABAQEBAQEBAQEBAQEAAAAAAAAAAAAAAAAAAAAAAAAAAAEBAQEBAQEBAQEBAQAAAAAAAAAAAAAAAAAAAAAAAAAAAQEBAQEBAQEBAQEBAAAAAAAAAAAAAAAAAAAAAAAAAAABAQEBAQEBAQEBAQEAAAAAAAAAAAAAAAAAAAAAAAAAAAEBAQEBAQEBAQEBAQAAAAAAAAAAAAAAAAAAAAAAAAAAAQEBAQEBAQEBAQEBAAAAAAAAAAAAAAAAAAAAAAAAAAABAQEBAQEBAQEBAQEAAAAAAAAAAAAAAAAAAAAAAAAAAAEBAQEBAQEBAQEBAQAAAAAAAAAAAAAAAAAAAQEBAQEBAQEBAQEBAQEBAQEBAAAAAAAAAAAAAAAAAAABAQEBAQEBAQEBAQEBAQEBAQEAAAAAAAAAAAAAAAAAAAEBAQEBAQEBAQEBAQEBAQEBAQAAAAAAAAAAAAAAAAAAAQEBAQEBAQEBAQEBAAAAAAAAAAAAAAAAAAAAAAAAAAABAQEBAQEBAQEBAQEAAAAAAAAAAAAAAAAAAAAAAAAAAAEBAQEBAQEBAQEBAQAAAAAAAAAAAAAAAAAAAQEBAQEBAQEBAQEBAQEBAQEBAAAAAAAAAAAAAAAAAAABAQEBAQEBAQEBAQEBAQEBAQEAAAAAAAAAAAAAAAAAAAEBAQEBAQEBAQEBAQEBAQEBAQAAAAAAAAAAAAAAAAAAAQEBAQEBAQEBAQEBAQEBAQEBAAAAAAAAAAAAAAAAAAABAQEBAQEBAQEBAQEBAQEBAQEAAAAAAAAAAAAAAAAAAAEBAQEBAQEBAQEBAQ==" - }, - "palette" : { - "originalArgb8888" : [ -265674 ], - "convertedRgb565" : [ -122 ] } }, "diagnostics" : [ ] @@ -1158,14 +1158,14 @@ "last_modified" : 1774359772489, "fingerprint" : "eeb7cc665386299403b7be1c272375d5077f3647c587f8033aa8c9275f840562", "metadata" : { + "palette" : { + "originalArgb8888" : [ -265674 ], + "convertedRgb565" : [ -122 ] + }, "tile" : { "width" : 32, "height" : 32, "paletteIndices" : "AQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAAAAAAAAAAABAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEAAAAAAAAAAAEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQAAAAAAAAAAAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAAAAAAAAAAABAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEAAAAAAAAAAAEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQAAAAAAAAAAAQEBAQEBAQEBAQEBAAAAAAAAAAAAAAAAAAAAAAAAAAABAQEBAQEBAQEBAQEAAAAAAAAAAAAAAAAAAAAAAAAAAAEBAQEBAQEBAQEBAQAAAAAAAAAAAAAAAAAAAAAAAAAAAQEBAQEBAQEBAQEBAAAAAAAAAAAAAAAAAAAAAAAAAAABAQEBAQEBAQEBAQEAAAAAAAAAAAAAAAAAAAAAAAAAAAEBAQEBAQEBAQEBAQAAAAAAAAAAAAAAAAAAAAAAAAAAAQEBAQEBAQEBAQEBAAAAAAAAAAAAAAAAAAAAAAAAAAABAQEBAQEBAQEBAQEAAAAAAAAAAAAAAAAAAAAAAAAAAAEBAQEBAQEBAQEBAQAAAAAAAAAAAAAAAAAAAQEBAQEBAQEBAQEBAQEBAQEBAAAAAAAAAAAAAAAAAAABAQEBAQEBAQEBAQEBAQEBAQEAAAAAAAAAAAAAAAAAAAEBAQEBAQEBAQEBAQEBAQEBAQAAAAAAAAAAAAAAAAAAAQEBAQEBAQEBAQEBAAAAAAAAAAAAAAAAAAAAAAAAAAABAQEBAQEBAQEBAQEAAAAAAAAAAAAAAAAAAAAAAAAAAAEBAQEBAQEBAQEBAQAAAAAAAAAAAAAAAAAAAQEBAQEBAQEBAQEBAQEBAQEBAAAAAAAAAAAAAAAAAAABAQEBAQEBAQEBAQEBAQEBAQEAAAAAAAAAAAAAAAAAAAEBAQEBAQEBAQEBAQEBAQEBAQAAAAAAAAAAAAAAAAAAAQEBAQEBAQEBAQEBAQEBAQEBAAAAAAAAAAAAAAAAAAABAQEBAQEBAQEBAQEBAQEBAQEAAAAAAAAAAAAAAAAAAAEBAQEBAQEBAQEBAQ==" - }, - "palette" : { - "originalArgb8888" : [ -265674 ], - "convertedRgb565" : [ -122 ] } }, "diagnostics" : [ ] @@ -1176,14 +1176,14 @@ "last_modified" : 1774359772491, "fingerprint" : "eeb7cc665386299403b7be1c272375d5077f3647c587f8033aa8c9275f840562", "metadata" : { + "palette" : { + "originalArgb8888" : [ -265674 ], + "convertedRgb565" : [ -122 ] + }, "tile" : { "width" : 32, "height" : 32, "paletteIndices" : "AQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAAAAAAAAAAABAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEAAAAAAAAAAAEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQAAAAAAAAAAAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAAAAAAAAAAABAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEAAAAAAAAAAAEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQAAAAAAAAAAAQEBAQEBAQEBAQEBAAAAAAAAAAAAAAAAAAAAAAAAAAABAQEBAQEBAQEBAQEAAAAAAAAAAAAAAAAAAAAAAAAAAAEBAQEBAQEBAQEBAQAAAAAAAAAAAAAAAAAAAAAAAAAAAQEBAQEBAQEBAQEBAAAAAAAAAAAAAAAAAAAAAAAAAAABAQEBAQEBAQEBAQEAAAAAAAAAAAAAAAAAAAAAAAAAAAEBAQEBAQEBAQEBAQAAAAAAAAAAAAAAAAAAAAAAAAAAAQEBAQEBAQEBAQEBAAAAAAAAAAAAAAAAAAAAAAAAAAABAQEBAQEBAQEBAQEAAAAAAAAAAAAAAAAAAAAAAAAAAAEBAQEBAQEBAQEBAQAAAAAAAAAAAAAAAAAAAQEBAQEBAQEBAQEBAQEBAQEBAAAAAAAAAAAAAAAAAAABAQEBAQEBAQEBAQEBAQEBAQEAAAAAAAAAAAAAAAAAAAEBAQEBAQEBAQEBAQEBAQEBAQAAAAAAAAAAAAAAAAAAAQEBAQEBAQEBAQEBAAAAAAAAAAAAAAAAAAAAAAAAAAABAQEBAQEBAQEBAQEAAAAAAAAAAAAAAAAAAAAAAAAAAAEBAQEBAQEBAQEBAQAAAAAAAAAAAAAAAAAAAQEBAQEBAQEBAQEBAQEBAQEBAAAAAAAAAAAAAAAAAAABAQEBAQEBAQEBAQEBAQEBAQEAAAAAAAAAAAAAAAAAAAEBAQEBAQEBAQEBAQEBAQEBAQAAAAAAAAAAAAAAAAAAAQEBAQEBAQEBAQEBAQEBAQEBAAAAAAAAAAAAAAAAAAABAQEBAQEBAQEBAQEBAQEBAQEAAAAAAAAAAAAAAAAAAAEBAQEBAQEBAQEBAQ==" - }, - "palette" : { - "originalArgb8888" : [ -265674 ], - "convertedRgb565" : [ -122 ] } }, "diagnostics" : [ ] @@ -1194,14 +1194,14 @@ "last_modified" : 1774359772492, "fingerprint" : "eeb7cc665386299403b7be1c272375d5077f3647c587f8033aa8c9275f840562", "metadata" : { + "palette" : { + "originalArgb8888" : [ -265674 ], + "convertedRgb565" : [ -122 ] + }, "tile" : { "width" : 32, "height" : 32, "paletteIndices" : "AQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAAAAAAAAAAABAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEAAAAAAAAAAAEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQAAAAAAAAAAAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAAAAAAAAAAABAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEAAAAAAAAAAAEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQAAAAAAAAAAAQEBAQEBAQEBAQEBAAAAAAAAAAAAAAAAAAAAAAAAAAABAQEBAQEBAQEBAQEAAAAAAAAAAAAAAAAAAAAAAAAAAAEBAQEBAQEBAQEBAQAAAAAAAAAAAAAAAAAAAAAAAAAAAQEBAQEBAQEBAQEBAAAAAAAAAAAAAAAAAAAAAAAAAAABAQEBAQEBAQEBAQEAAAAAAAAAAAAAAAAAAAAAAAAAAAEBAQEBAQEBAQEBAQAAAAAAAAAAAAAAAAAAAAAAAAAAAQEBAQEBAQEBAQEBAAAAAAAAAAAAAAAAAAAAAAAAAAABAQEBAQEBAQEBAQEAAAAAAAAAAAAAAAAAAAAAAAAAAAEBAQEBAQEBAQEBAQAAAAAAAAAAAAAAAAAAAQEBAQEBAQEBAQEBAQEBAQEBAAAAAAAAAAAAAAAAAAABAQEBAQEBAQEBAQEBAQEBAQEAAAAAAAAAAAAAAAAAAAEBAQEBAQEBAQEBAQEBAQEBAQAAAAAAAAAAAAAAAAAAAQEBAQEBAQEBAQEBAAAAAAAAAAAAAAAAAAAAAAAAAAABAQEBAQEBAQEBAQEAAAAAAAAAAAAAAAAAAAAAAAAAAAEBAQEBAQEBAQEBAQAAAAAAAAAAAAAAAAAAAQEBAQEBAQEBAQEBAQEBAQEBAAAAAAAAAAAAAAAAAAABAQEBAQEBAQEBAQEBAQEBAQEAAAAAAAAAAAAAAAAAAAEBAQEBAQEBAQEBAQEBAQEBAQAAAAAAAAAAAAAAAAAAAQEBAQEBAQEBAQEBAQEBAQEBAAAAAAAAAAAAAAAAAAABAQEBAQEBAQEBAQEBAQEBAQEAAAAAAAAAAAAAAAAAAAEBAQEBAQEBAQEBAQ==" - }, - "palette" : { - "originalArgb8888" : [ -265674 ], - "convertedRgb565" : [ -122 ] } }, "diagnostics" : [ ] @@ -1212,14 +1212,14 @@ "last_modified" : 1774359772493, "fingerprint" : "eeb7cc665386299403b7be1c272375d5077f3647c587f8033aa8c9275f840562", "metadata" : { + "palette" : { + "originalArgb8888" : [ -265674 ], + "convertedRgb565" : [ -122 ] + }, "tile" : { "width" : 32, "height" : 32, "paletteIndices" : "AQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAAAAAAAAAAABAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEAAAAAAAAAAAEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQAAAAAAAAAAAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAAAAAAAAAAABAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEAAAAAAAAAAAEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQAAAAAAAAAAAQEBAQEBAQEBAQEBAAAAAAAAAAAAAAAAAAAAAAAAAAABAQEBAQEBAQEBAQEAAAAAAAAAAAAAAAAAAAAAAAAAAAEBAQEBAQEBAQEBAQAAAAAAAAAAAAAAAAAAAAAAAAAAAQEBAQEBAQEBAQEBAAAAAAAAAAAAAAAAAAAAAAAAAAABAQEBAQEBAQEBAQEAAAAAAAAAAAAAAAAAAAAAAAAAAAEBAQEBAQEBAQEBAQAAAAAAAAAAAAAAAAAAAAAAAAAAAQEBAQEBAQEBAQEBAAAAAAAAAAAAAAAAAAAAAAAAAAABAQEBAQEBAQEBAQEAAAAAAAAAAAAAAAAAAAAAAAAAAAEBAQEBAQEBAQEBAQAAAAAAAAAAAAAAAAAAAQEBAQEBAQEBAQEBAQEBAQEBAAAAAAAAAAAAAAAAAAABAQEBAQEBAQEBAQEBAQEBAQEAAAAAAAAAAAAAAAAAAAEBAQEBAQEBAQEBAQEBAQEBAQAAAAAAAAAAAAAAAAAAAQEBAQEBAQEBAQEBAAAAAAAAAAAAAAAAAAAAAAAAAAABAQEBAQEBAQEBAQEAAAAAAAAAAAAAAAAAAAAAAAAAAAEBAQEBAQEBAQEBAQAAAAAAAAAAAAAAAAAAAQEBAQEBAQEBAQEBAQEBAQEBAAAAAAAAAAAAAAAAAAABAQEBAQEBAQEBAQEBAQEBAQEAAAAAAAAAAAAAAAAAAAEBAQEBAQEBAQEBAQEBAQEBAQAAAAAAAAAAAAAAAAAAAQEBAQEBAQEBAQEBAQEBAQEBAAAAAAAAAAAAAAAAAAABAQEBAQEBAQEBAQEBAQEBAQEAAAAAAAAAAAAAAAAAAAEBAQEBAQEBAQEBAQ==" - }, - "palette" : { - "originalArgb8888" : [ -265674 ], - "convertedRgb565" : [ -122 ] } }, "diagnostics" : [ ] @@ -1230,14 +1230,14 @@ "last_modified" : 1774359772494, "fingerprint" : "eeb7cc665386299403b7be1c272375d5077f3647c587f8033aa8c9275f840562", "metadata" : { + "palette" : { + "originalArgb8888" : [ -265674 ], + "convertedRgb565" : [ -122 ] + }, "tile" : { "width" : 32, "height" : 32, "paletteIndices" : "AQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAAAAAAAAAAABAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEAAAAAAAAAAAEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQAAAAAAAAAAAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAAAAAAAAAAABAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEAAAAAAAAAAAEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQAAAAAAAAAAAQEBAQEBAQEBAQEBAAAAAAAAAAAAAAAAAAAAAAAAAAABAQEBAQEBAQEBAQEAAAAAAAAAAAAAAAAAAAAAAAAAAAEBAQEBAQEBAQEBAQAAAAAAAAAAAAAAAAAAAAAAAAAAAQEBAQEBAQEBAQEBAAAAAAAAAAAAAAAAAAAAAAAAAAABAQEBAQEBAQEBAQEAAAAAAAAAAAAAAAAAAAAAAAAAAAEBAQEBAQEBAQEBAQAAAAAAAAAAAAAAAAAAAAAAAAAAAQEBAQEBAQEBAQEBAAAAAAAAAAAAAAAAAAAAAAAAAAABAQEBAQEBAQEBAQEAAAAAAAAAAAAAAAAAAAAAAAAAAAEBAQEBAQEBAQEBAQAAAAAAAAAAAAAAAAAAAQEBAQEBAQEBAQEBAQEBAQEBAAAAAAAAAAAAAAAAAAABAQEBAQEBAQEBAQEBAQEBAQEAAAAAAAAAAAAAAAAAAAEBAQEBAQEBAQEBAQEBAQEBAQAAAAAAAAAAAAAAAAAAAQEBAQEBAQEBAQEBAAAAAAAAAAAAAAAAAAAAAAAAAAABAQEBAQEBAQEBAQEAAAAAAAAAAAAAAAAAAAAAAAAAAAEBAQEBAQEBAQEBAQAAAAAAAAAAAAAAAAAAAQEBAQEBAQEBAQEBAQEBAQEBAAAAAAAAAAAAAAAAAAABAQEBAQEBAQEBAQEBAQEBAQEAAAAAAAAAAAAAAAAAAAEBAQEBAQEBAQEBAQEBAQEBAQAAAAAAAAAAAAAAAAAAAQEBAQEBAQEBAQEBAQEBAQEBAAAAAAAAAAAAAAAAAAABAQEBAQEBAQEBAQEBAQEBAQEAAAAAAAAAAAAAAAAAAAEBAQEBAQEBAQEBAQ==" - }, - "palette" : { - "originalArgb8888" : [ -265674 ], - "convertedRgb565" : [ -122 ] } }, "diagnostics" : [ ] @@ -1248,14 +1248,14 @@ "last_modified" : 1774359772495, "fingerprint" : "eeb7cc665386299403b7be1c272375d5077f3647c587f8033aa8c9275f840562", "metadata" : { + "palette" : { + "originalArgb8888" : [ -265674 ], + "convertedRgb565" : [ -122 ] + }, "tile" : { "width" : 32, "height" : 32, "paletteIndices" : "AQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAAAAAAAAAAABAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEAAAAAAAAAAAEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQAAAAAAAAAAAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAAAAAAAAAAABAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEAAAAAAAAAAAEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQAAAAAAAAAAAQEBAQEBAQEBAQEBAAAAAAAAAAAAAAAAAAAAAAAAAAABAQEBAQEBAQEBAQEAAAAAAAAAAAAAAAAAAAAAAAAAAAEBAQEBAQEBAQEBAQAAAAAAAAAAAAAAAAAAAAAAAAAAAQEBAQEBAQEBAQEBAAAAAAAAAAAAAAAAAAAAAAAAAAABAQEBAQEBAQEBAQEAAAAAAAAAAAAAAAAAAAAAAAAAAAEBAQEBAQEBAQEBAQAAAAAAAAAAAAAAAAAAAAAAAAAAAQEBAQEBAQEBAQEBAAAAAAAAAAAAAAAAAAAAAAAAAAABAQEBAQEBAQEBAQEAAAAAAAAAAAAAAAAAAAAAAAAAAAEBAQEBAQEBAQEBAQAAAAAAAAAAAAAAAAAAAQEBAQEBAQEBAQEBAQEBAQEBAAAAAAAAAAAAAAAAAAABAQEBAQEBAQEBAQEBAQEBAQEAAAAAAAAAAAAAAAAAAAEBAQEBAQEBAQEBAQEBAQEBAQAAAAAAAAAAAAAAAAAAAQEBAQEBAQEBAQEBAAAAAAAAAAAAAAAAAAAAAAAAAAABAQEBAQEBAQEBAQEAAAAAAAAAAAAAAAAAAAAAAAAAAAEBAQEBAQEBAQEBAQAAAAAAAAAAAAAAAAAAAQEBAQEBAQEBAQEBAQEBAQEBAAAAAAAAAAAAAAAAAAABAQEBAQEBAQEBAQEBAQEBAQEAAAAAAAAAAAAAAAAAAAEBAQEBAQEBAQEBAQEBAQEBAQAAAAAAAAAAAAAAAAAAAQEBAQEBAQEBAQEBAQEBAQEBAAAAAAAAAAAAAAAAAAABAQEBAQEBAQEBAQEBAQEBAQEAAAAAAAAAAAAAAAAAAAEBAQEBAQEBAQEBAQ==" - }, - "palette" : { - "originalArgb8888" : [ -265674 ], - "convertedRgb565" : [ -122 ] } }, "diagnostics" : [ ] @@ -1266,14 +1266,14 @@ "last_modified" : 1775797786950, "fingerprint" : "0526996900bdeef23c72fe987fb45800f11895946dcd5f0f7f8390c879069a37", "metadata" : { + "palette" : { + "originalArgb8888" : [ -265674, -1736296, -13905598, -11518505, -14439577, -2467509 ], + "convertedRgb565" : [ -122, -7149, 11912, 20986, 9548, -9527 ] + }, "tile" : { "width" : 32, "height" : 32, "paletteIndices" : "AQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQECAgIBAQEBAQEBAQEBAQEBAQEBAwMDAwMDAQEBAQEBAgICAgICAgIBAQEBAQEBAQEBAQMDAwMDAwMBAQEBAQICAgICAgICAQEBAQEBAQEBAQEBAQMDAwMDAQEBAQEBAgICAgICAgEBAQEBAQQEBAQBAQEBAQEBAQEBAQEBAQEBAgICAgIBAQEBAQEEBAQEBAQBAQEBAQEBAQEBAQEBAQEBAgECAQEBAQEBAQQEBAQEAQEBAQEBAAAAAAAAAAABAQECAQEBAQEBAQEEBAQEBAEBAQEBAQEAAAAAAAAAAAEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQAAAAAAAAAAAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAAAAAAAAAAABAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEAAAAAAAAAAAEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQAAAAAAAAAAAQEBAQEBAQEBAQEBAAAAAAAAAAAAAAAAAAAAAAAAAAABAQEBAQEBAQEBAQEAAAAAAAAAAAAAAAAAAAAAAAAAAAEBAQEBAQEBAQEBAQAAAAAAAAAAAAAAAAAAAAAAAAAAAQEBAQEBAQUBAQEBAAAAAAAAAAAAAAAAAAAAAAAAAAABAQEBAQUFBQEBAQEAAAAAAAAAAAAAAAAAAAAAAAAAAAEBAQEFBQUFBQEBAQAAAAAAAAAAAAAAAAAAAAAAAAAAAQEBBQUFBQUBAQEBAAAAAAAAAAAAAAAAAAAAAAAAAAABAQEBBQUFAQEBAQEAAAAAAAAAAAAAAAAAAAAAAAAAAAEBAQEBAQEBAQEBAQAAAAAAAAAAAAAAAAAAAQEBAQEBAQEBAQEBAQEBAQEBAAAAAAAAAAAAAAAAAAABAQEBAQEBAQEBAQEBAQEBAQEAAAAAAAAAAAAAAAAAAAEBAQEBAQYGBgYBAQEBAQEBAQAAAAAAAAAAAAAAAAAAAQEBAQEBBgYGBgEBAAAAAAAAAAAAAAAAAAAAAAAAAAABAQEBAQEGBgYGAQEAAAAAAAAAAAAAAAAAAAAAAAAAAAEBAQEBAQYGBgYBAQAAAAAAAAAAAAAAAAAAAQEBAQEBAQEBAQEBAQYGAQEBAAAAAAAAAAAAAAAAAAABAQEBAQEBAQEBAQEBAQEBAQEAAAAAAAAAAAAAAAAAAAEBAQEBAQEBAQEBAQEBAQEBAQAAAAAAAAAAAAAAAAAAAQEBAQEBAQEBAQEBAQEBAQEBAAAAAAAAAAAAAAAAAAABAQEBAQEBAQEBAQEBAQEBAQEAAAAAAAAAAAAAAAAAAAEBAQEBAQEBAQEBAQ==" - }, - "palette" : { - "originalArgb8888" : [ -265674, -1736296, -13905598, -11518505, -14439577, -2467509 ], - "convertedRgb565" : [ -122, -7149, 11912, 20986, 9548, -9527 ] } }, "diagnostics" : [ ] @@ -1314,14 +1314,14 @@ "last_modified" : 1775797786770, "fingerprint" : "aa7d241deabcebe29a6096e14eaf16fdc06cf06380c11a507620b00fc7bff094", "metadata" : { + "palette" : { + "originalArgb8888" : [ -265674 ], + "convertedRgb565" : [ -122 ] + }, "tile" : { "width" : 16, "height" : 16, "paletteIndices" : "AQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAAAAAAEBAQEBAQEBAQEBAQAAAAABAQEBAQEBAQEBAQEAAAAAAQEBAQEBAAAAAAAAAAAAAAEBAQEBAQAAAAAAAAAAAAABAQEBAQEAAAAAAAAAAAAAAQEBAQEBAAAAAAAAAAAAAAEBAQEBAQAAAAAAAAABAQEBAQEBAQEAAAAAAAAAAQEBAQEBAAAAAAAAAAAAAAEBAQEBAQAAAAAAAAABAQEBAQEBAQEAAAAAAAAAAQEBAQEBAQEBAAAAAAAAAAEBAQEBAQ==" - }, - "palette" : { - "originalArgb8888" : [ -265674 ], - "convertedRgb565" : [ -122 ] } }, "diagnostics" : [ ] @@ -1344,14 +1344,14 @@ "last_modified" : 1775797786709, "fingerprint" : "6ca635a7906067b6a2a8460a8562718c445783e6df18b9f2c80c83c5ac569db6", "metadata" : { + "palette" : { + "originalArgb8888" : [ -130562, -14145496, -2043712, -460560, -13082456, -6252424, -10977088 ], + "convertedRgb565" : [ -2017, 10565, -6504, -34, 15125, -23345, 23576 ] + }, "tile" : { "width" : 32, "height" : 32, "paletteIndices" : "AQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQICAgICAgICAgAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAICAwMDAwMDAgAAAAAAAAAAAAACAgIAAAAAAAAAAAAAAAIEBQUFBQUDAgAAAAAAAgICAgMDAwIAAAAAAAAAAAAAAgQFAwYGBgUDAgICAgIDAwMDBQUFAwIAAAAAAAAAAAACBAUDBgYGBgUEBAQEAwUFBQUGAwMFBAICAAAAAAAAAAIEBQMGBgYGAwUFBwcFBgYGBgMDAwMFBAQCAgAAAAAAAgQFAwYGBgMDAwQEBAMGBgYGBgMDAwMHBwQDAgAAAAACBAUDBgYGAwMDAwQEAwYGBgYGAwMDBAQEBQUDAgIAAAIEBQMGBgYDAwMDBAQDBgYGBgYDAwMDBAQDAwUGAgAAAgQFAwYGBgMDAwMEBAMGBgYGBQUFBQUEBAUFBgIAAAACBAUDBgYGAwMDAwQEAwYGBQUGAwMDAwcHAwYCAAAAAAIEBQMFBQUFBQMDBAQDBgUGBgICAgICBAQCAgAAAAAAAgQFBQYGBgYDBQMEBAMFBgICAAAAAAACAgAAAAAAAAACBAMDBgICAgIDBQcHBQYCAAAAAAAAAAAAAAAAAAAAAgIDAwMCAAAAAAIEBAMDAgAAAAAAAAAAAAAAAAAAAAICAgICAgAAAAAAAAICAgIAAAAAAAAAAAAAAAAAAAAAAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQ==" - }, - "palette" : { - "originalArgb8888" : [ -130562, -14145496, -2043712, -460560, -13082456, -6252424, -10977088 ], - "convertedRgb565" : [ -2017, 10565, -6504, -34, 15125, -23345, 23576 ] } }, "diagnostics" : [ { @@ -1396,14 +1396,14 @@ "last_modified" : 1775797786706, "fingerprint" : "7feab8c868bb446afd3dd7250e70504fb0ca228f463650d2dd7c525144e0b321", "metadata" : { + "palette" : { + "originalArgb8888" : [ -16777216, -2109505, -526353, -395279, -130562, -13082456, -10911807, -6318217, -6186631, -6187143, -6318215, -13148249, -13016663, -14080215 ], + "convertedRgb565" : [ 0, -8585, -2115, -66, -2017, 15125, 23544, -25426, -23345, -23377, -25425, 13044, 15125, 10533 ] + }, "tile" : { "width" : 32, "height" : 32, "paletteIndices" : "AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAEBAQEBAQEAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAEBAgMDBAEBAQEBBQUFAAUFBQUFBQUBAQAAAAAAAAAAAAECBgcHBAIICAkBBQUFBQUFBQEBAQICAQEAAAAFBQAAAQIGAwMHBgYGBgIBBQUFBQEBCgIIBgYDBAEBBQUFAAABAgYDAwIJCQsJBgIBAQEBCAgMDA0JAgcHAwMBBQUAAAECBgMDAgsLCwsLBgMDAwIGBgkCCwILAgIHAwEFBQAAAQIGAwMCCQkJCQkCBgcHBgsLCwsCCwICAwMHAwEFAAABAgYDAgkJCQkJCQICAwMCCQkJAgkGBgYHBwcDDgUAAAECBwMCCQkJCQkJAgIDAgkJCQkGBgsCAwMDAwQEAQAAAQIHAwIJCQkJCQkCAgMCCQkJBgkLAQEBAQEBAQQBAAABAgcDAgkJCQkJAgICAwILCQYJAQEFBQUFBQUFAQEAAAECBwMCCQkJCQYGAgIDAgkGCwEFBQUFBQUFBQAAAAAAAQIHAwIJCQYGCQIGBgcMBgkBBQUFBQUFBQAAAAAAAAABAgcGBgYGCQsBAQIDBAIKAQUFBQUFBQAAAAAAAAAAAQECAwIJCQkBAQAAAQEBAQEAAAAAAAAAAAAAAAAAAAEBAQEBAQEBAQAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA==" - }, - "palette" : { - "originalArgb8888" : [ -16777216, -2109505, -526353, -395279, -130562, -13082456, -10911807, -6318217, -6186631, -6187143, -6318215, -13148249, -13016663, -14080215 ], - "convertedRgb565" : [ 0, -8585, -2115, -66, -2017, 15125, 23544, -25426, -23345, -23377, -25425, 13044, 15125, 10533 ] } }, "diagnostics" : [ ] @@ -1414,14 +1414,14 @@ "last_modified" : 1775797786710, "fingerprint" : "c363f3ef7f32d9b249c7dc8babdb3eb5aae68c524099e5e97290202b054dda71", "metadata" : { + "palette" : { + "originalArgb8888" : [ -14671840, -11431408, -9326048, -802016, -3964416, -5086944, -789517, -810399, -1863087, -10403552, -5078447 ], + "convertedRgb565" : [ 8452, 21634, 30084, -2556, -15360, -19708, -2146, -2804, -7030, 25092, -19446 ] + }, "tile" : { "width" : 32, "height" : 32, "paletteIndices" : "AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAABAQEBAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAEBAQICAwMBAQAAAAAAAAAAAAAAAAAAAAAAAAAAAAABBAQBAgIDAwMCAQAAAAAAAAAAAAAAAAAAAAAAAAAAAQUFBAQBAgIDAgICAQAAAAAAAAAAAAAAAAAAAAAAAAABBQEFBAUBAgICAgMBAAAAAAAAAAAAAAAAAAAAAAAAAAABBgEFBQUBAgECAgMBAAAAAAAAAAAAAAAAAAAAAAAAAAEGBwEFBAEBCAECAwEAAAAAAAAAAAAAAAAAAAAAAAAAAQgBBwEEAQgJAQICAQAAAAAAAAAAAAAAAAAAAAAAAAEICAEHAQQBCQYBAgIBAAAAAAAAAAAAAAAAAAAAAAAAAAEGCQkBBQEGAQUBAgEAAAAAAAAAAAAAAAAAAAAAAAAAAAEBBgYBBgEBAQABAAAAAAAAAAAAAAAAAAAAAAAAAAAAAQcBAQEBAgIBAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAECAwECAwIBAgEAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAQECAQcHBwECAQAAAAAAAAAAAAAAAAAAAAAAAAAAAAABBAEBAQEBAQECAQAAAAAAAAAAAAAAAAAAAAAAAAAAAAABAgEJCgoBAgEAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAQEBAQEJCQEBAQAAAAAAAAAAAAAAAAAAAAAAAAAAAAEBAQEKAQEBAQEBAQAAAAAAAAAAAAAAAAAAAAAAAAAAAQEBAQELCwoKAQEBAAAAAAAAAAAAAAAAAAAAAAAAAAAAAQEBAQEBAQEBAQAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAEBAQEBAQAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA==" - }, - "palette" : { - "originalArgb8888" : [ -14671840, -11431408, -9326048, -802016, -3964416, -5086944, -789517, -810399, -1863087, -10403552, -5078447 ], - "convertedRgb565" : [ 8452, 21634, 30084, -2556, -15360, -19708, -2146, -2804, -7030, 25092, -19446 ] } }, "diagnostics" : [ ] @@ -1432,14 +1432,14 @@ "last_modified" : 1775797786711, "fingerprint" : "e2130efbb9643b41a4fb62619f2713402f9622c7db040fe18d929609ef70b89a", "metadata" : { + "palette" : { + "originalArgb8888" : [ -14671840, -11431408, -9326048, -802016, -3964416, -5086944, -789517, -810399, -1863087, -10403552, -5078447 ], + "convertedRgb565" : [ 8452, 21634, 30084, -2556, -15360, -19708, -2146, -2804, -7030, 25092, -19446 ] + }, "tile" : { "width" : 32, "height" : 32, "paletteIndices" : "AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAQEBAQAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAABAQECAgMDAQEAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAQQEAQICAwMDAgEAAAAAAAAAAAAAAAAAAAAAAAAAAAEFBQQEAQICAwICAgEAAAAAAAAAAAAAAAAAAAAAAAAAAQUBBQQFAQICAgIDAQAAAAAAAAAAAAAAAAAAAAAAAAAAAQYBBQUFAQIBAgIDAQAAAAAAAAAAAAAAAAAAAAAAAAABBgcBBQQBAQgBAgMBAAAAAAAAAAAAAAAAAAAAAAAAAAEIAQcBBAEICQECAgEAAAAAAAAAAAAAAAAAAAAAAAABCAgBBwEEAQkGAQICAQAAAAAAAAAAAAAAAAAAAAAAAAABBgkJAQUBBgEFAQIBAAAAAAAAAAAAAAAAAAAAAAAAAAABAQYGAQYBAQEAAQAAAAAAAAAAAAAAAAAAAAAAAAAAAAEHAQEBAQECAQAAAAAAAAAAAAAAAAAAAAAAAAAAAAABAgEBBwMBAwMBAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAEBCQoBBwEDAgEBAAAAAAAAAAAAAAAAAAAAAAAAAAABAgEJCQoBAgIBAQIBAAAAAAAAAAAAAAAAAAAAAAAAAAECAgEBAQICAQECAQEAAAAAAAAAAAAAAAAAAAAAAAAAAAEBAgECAQECAgEBAQAAAAAAAAAAAAAAAAAAAAAAAAAAAQEBAQICAgEBAQoKAQAAAAAAAAAAAAAAAAAAAAAAAAEBAQEBAQEBAQELCwoBAAAAAAAAAAAAAAAAAAAAAAAAAQEBAQEBAQEBAQsLAQEAAAAAAAAAAAAAAAAAAAAAAAAAAQEBAQEBAQEBAQEBAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAEBAQEBAQAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA==" - }, - "palette" : { - "originalArgb8888" : [ -14671840, -11431408, -9326048, -802016, -3964416, -5086944, -789517, -810399, -1863087, -10403552, -5078447 ], - "convertedRgb565" : [ 8452, 21634, 30084, -2556, -15360, -19708, -2146, -2804, -7030, 25092, -19446 ] } }, "diagnostics" : [ ] @@ -1450,14 +1450,14 @@ "last_modified" : 1775797786713, "fingerprint" : "9216dfc6a6226fac398e9f781550d23fbfaa65bd377cdda69187149beca114ec", "metadata" : { + "palette" : { + "originalArgb8888" : [ -14671840, -11431408, -9326048, -802016, -3964416, -5086944, -789517, -810399, -1863087, -10403552, -5078447 ], + "convertedRgb565" : [ 8452, 21634, 30084, -2556, -15360, -19708, -2146, -2804, -7030, 25092, -19446 ] + }, "tile" : { "width" : 32, "height" : 32, "paletteIndices" : "AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAQEBAQAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAEBAQECAgMDAQEAAAEBAAAAAAAAAAAAAAAAAAAAAAABBAQEAQICAwMDAgEBAwEAAAAAAAAAAAAAAAAAAAAAAAEFBQQEAQICAwICAQIDAQAAAAAAAAAAAAAAAAAAAAAAAAEBBQQFAQICAgICAwEBAAAAAAAAAAAAAAAAAAAAAAAAAQYBBQUFAQIBAgICAQAAAAAAAAAAAAAAAAAAAAAAAAABBgcBBQQFAQgBAQEBAAAAAAAAAAAAAAAAAAAAAAAAAAEIAQcBBAUBCQEBBQUBAAAAAAAAAAAAAAAAAAAAAAABCAgBBwgBBAUBAQUBAAAAAAAAAAAAAAAAAAAAAAAAAAABBgkJBgYBAQEBAQAAAAAAAAAAAAAAAAAAAAAAAAAAAAABAQYGBgYBAQAAAAAAAAAAAAAAAAAAAAAAAAAAAAABAQEBAQEBAQMBAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAEJCgEHAwECAwEBAQAAAAAAAAAAAAAAAAAAAAAAAAABAQkKAQcCAQIDAQEBAQAAAAAAAAAAAAAAAAAAAAAAAAEKAQEBAQECAgEBAgELAQAAAAAAAAAAAAAAAAAAAAAAAQEKAQICAQEBAgIBAQoLAQAAAAAAAAAAAAAAAAAAAAAAAQEBAQECAgICAQEAAQEAAAAAAAAAAAAAAAAAAAAAAAAAAQEBAQEBAQEBAQAAAAAAAAAAAAAAAAAAAAAAAAAAAAEBAQEBAQEBAQEBAQAAAAAAAAAAAAAAAAAAAAAAAAAAAQEBAQEBAQEBAQEBAAAAAAAAAAAAAAAAAAAAAAAAAAAAAQEBAQEBAQEBAQAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAEBAQEBAQAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA==" - }, - "palette" : { - "originalArgb8888" : [ -14671840, -11431408, -9326048, -802016, -3964416, -5086944, -789517, -810399, -1863087, -10403552, -5078447 ], - "convertedRgb565" : [ 8452, 21634, 30084, -2556, -15360, -19708, -2146, -2804, -7030, 25092, -19446 ] } }, "diagnostics" : [ ] @@ -1468,14 +1468,14 @@ "last_modified" : 1775797786712, "fingerprint" : "ebc4b7ca7bb1455288681c5d71424f60f658a44cb343d0c3934329cec676c867", "metadata" : { + "palette" : { + "originalArgb8888" : [ -14671840, -11431408, -9326048, -802016, -3964416, -5086944, -789517, -810399, -1863087, -10403552, -5078447 ], + "convertedRgb565" : [ 8452, 21634, 30084, -2556, -15360, -19708, -2146, -2804, -7030, 25092, -19446 ] + }, "tile" : { "width" : 32, "height" : 32, "paletteIndices" : "AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAABAQEBAAAAAAEBAAAAAAAAAAAAAAAAAAAAAAAAAAEBAQICAwMBAQEBAwEAAAAAAAAAAAAAAAAAAAAAAAABBAQBAgIDAwMCAQMDAQAAAAAAAAAAAAAAAAAAAAAAAQUFBAQBAgIDAgICAwIBAAAAAAAAAAAAAAAAAAAAAAABBQEFBAUBAgICAgMCAQAAAAAAAAAAAAAAAAAAAAAAAAABBgEFBQUBAgECAgIBAAAAAAAAAAAAAAAAAAAAAAAAAAEGBwEFBAUBCAEBAQAAAAAAAAAAAAAAAAAAAAAAAAAAAQgBBwEEBQEJAQEAAAAAAAAAAAAAAAAAAAAAAAAAAAEICAEHCQEEBQEFAQAAAAAAAAAAAAAAAAAAAAAAAAAAAQEBCQkGBgEBAQUBAAAAAAAAAAAAAAAAAAAAAAAAAAABCQoBAQEGBgEBAQUBAAAAAAAAAAAAAAAAAAAAAAAAAAEKCgEHAgEBAQMBAQAAAAAAAAAAAAAAAAAAAAAAAAAAAAEBBwICAQIDAwEBAAAAAAAAAAAAAAAAAAAAAAAAAAABAQEBAQECAgMBAQIBAAAAAAAAAAAAAAAAAAAAAAAAAQoBAQIBAgICAgECAQEAAAAAAAAAAAAAAAAAAAAAAAABCgoBAgIBAQEBAgELAQAAAAAAAAAAAAAAAAAAAAAAAAEBAQEBAQICAgIBAQEAAAAAAAAAAAAAAAAAAAAAAAAAAAEBAQEBAQEBAQEBAQAAAAAAAAAAAAAAAAAAAAAAAAAAAQEBAQEBAQEBAQEBAAAAAAAAAAAAAAAAAAAAAAAAAAAAAQEBAQEBAQEBAQAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAEBAQEBAQAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA==" - }, - "palette" : { - "originalArgb8888" : [ -14671840, -11431408, -9326048, -802016, -3964416, -5086944, -789517, -810399, -1863087, -10403552, -5078447 ], - "convertedRgb565" : [ 8452, 21634, 30084, -2556, -15360, -19708, -2146, -2804, -7030, 25092, -19446 ] } }, "diagnostics" : [ ] @@ -1486,14 +1486,14 @@ "last_modified" : 1775797786718, "fingerprint" : "c363f3ef7f32d9b249c7dc8babdb3eb5aae68c524099e5e97290202b054dda71", "metadata" : { + "palette" : { + "originalArgb8888" : [ -14671840, -11431408, -9326048, -802016, -3964416, -5086944, -789517, -810399, -1863087, -10403552, -5078447 ], + "convertedRgb565" : [ 8452, 21634, 30084, -2556, -15360, -19708, -2146, -2804, -7030, 25092, -19446 ] + }, "tile" : { "width" : 32, "height" : 32, "paletteIndices" : "AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAABAQEBAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAEBAQICAwMBAQAAAAAAAAAAAAAAAAAAAAAAAAAAAAABBAQBAgIDAwMCAQAAAAAAAAAAAAAAAAAAAAAAAAAAAQUFBAQBAgIDAgICAQAAAAAAAAAAAAAAAAAAAAAAAAABBQEFBAUBAgICAgMBAAAAAAAAAAAAAAAAAAAAAAAAAAABBgEFBQUBAgECAgMBAAAAAAAAAAAAAAAAAAAAAAAAAAEGBwEFBAEBCAECAwEAAAAAAAAAAAAAAAAAAAAAAAAAAQgBBwEEAQgJAQICAQAAAAAAAAAAAAAAAAAAAAAAAAEICAEHAQQBCQYBAgIBAAAAAAAAAAAAAAAAAAAAAAAAAAEGCQkBBQEGAQUBAgEAAAAAAAAAAAAAAAAAAAAAAAAAAAEBBgYBBgEBAQABAAAAAAAAAAAAAAAAAAAAAAAAAAAAAQcBAQEBAgIBAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAECAwECAwIBAgEAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAQECAQcHBwECAQAAAAAAAAAAAAAAAAAAAAAAAAAAAAABBAEBAQEBAQECAQAAAAAAAAAAAAAAAAAAAAAAAAAAAAABAgEJCgoBAgEAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAQEBAQEJCQEBAQAAAAAAAAAAAAAAAAAAAAAAAAAAAAEBAQEKAQEBAQEBAQAAAAAAAAAAAAAAAAAAAAAAAAAAAQEBAQELCwoKAQEBAAAAAAAAAAAAAAAAAAAAAAAAAAAAAQEBAQEBAQEBAQAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAEBAQEBAQAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA==" - }, - "palette" : { - "originalArgb8888" : [ -14671840, -11431408, -9326048, -802016, -3964416, -5086944, -789517, -810399, -1863087, -10403552, -5078447 ], - "convertedRgb565" : [ 8452, 21634, 30084, -2556, -15360, -19708, -2146, -2804, -7030, 25092, -19446 ] } }, "diagnostics" : [ ] @@ -1504,14 +1504,14 @@ "last_modified" : 1775797786717, "fingerprint" : "1ba8ce75c445396334737143e0cfa56c87a1fb64cca8ad0962192594849249eb", "metadata" : { + "palette" : { + "originalArgb8888" : [ -14671840, -11431408, -9326048, -802016, -3964416, -5086944, -789517, -810399, -1863087, -10403552 ], + "convertedRgb565" : [ 8452, 21634, 30084, -2556, -15360, -19708, -2146, -2804, -7030, 25092 ] + }, "tile" : { "width" : 32, "height" : 32, "paletteIndices" : "AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAABAQEBAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAEBAQICAwMBAQAAAAAAAAAAAAAAAAAAAAAAAAAAAAABBAQBAgIDAwMCAQAAAAAAAAAAAAAAAAAAAAAAAAAAAQUFBAQBAgIDAgICAQAAAAAAAAAAAAAAAAAAAAAAAAABBQEFBAUBAgICAgMBAAAAAAAAAAAAAAAAAAAAAAAAAAABBgEFBQUBAgECAgMBAAAAAAAAAAAAAAAAAAAAAAAAAAEGBwEFBAEBCAECAwEAAAAAAAAAAAAAAAAAAAAAAAAAAQgBBwEEAQgJAQICAQAAAAAAAAAAAAAAAAAAAAAAAAEICAEHAQQBCQYBAgIBAAAAAAAAAAAAAAAAAAAAAAAAAAEGCQkBBQEGAQUBAgEAAAAAAAAAAAAAAAAAAAAAAAAAAAEBBgYBAQEBAQABAAAAAAAAAAAAAAAAAAAAAAAAAAAAAQcBAQEDAQEAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAABAwMBAgcHAQAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAQMDAwIBAQEBAQAAAAAAAAAAAAAAAAAAAAAAAAAAAAABBAIDAgEKCgECAQAAAAAAAAAAAAAAAAAAAAAAAAAAAAECAQEBAQkJAQIBAAAAAAAAAAAAAAAAAAAAAAAAAAAAAQECAgICAQECAQoBAAAAAAAAAAAAAAAAAAAAAAAAAAABAQEBAQICAgEKCgEAAAAAAAAAAAAAAAAAAAAAAAAAAQEBAQEBAQEBCgoKAQAAAAAAAAAAAAAAAAAAAAAAAAABAQEBAQEBAQEBAQEAAAAAAAAAAAAAAAAAAAAAAAAAAAABAQEBAQEBAQEBAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAQEBAQEBAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA==" - }, - "palette" : { - "originalArgb8888" : [ -14671840, -11431408, -9326048, -802016, -3964416, -5086944, -789517, -810399, -1863087, -10403552 ], - "convertedRgb565" : [ 8452, 21634, 30084, -2556, -15360, -19708, -2146, -2804, -7030, 25092 ] } }, "diagnostics" : [ ] @@ -1522,14 +1522,14 @@ "last_modified" : 1775797786714, "fingerprint" : "5e0954447699c6d5eac7550f1a10cf520efcddad0b9fbd9a716434da9d9550d4", "metadata" : { + "palette" : { + "originalArgb8888" : [ -14671840, -11431408, -9326048, -802016, -3964416, -5086944, -789517, -810399, -1863087, -10403552, -5078447 ], + "convertedRgb565" : [ 8452, 21634, 30084, -2556, -15360, -19708, -2146, -2804, -7030, 25092, -19446 ] + }, "tile" : { "width" : 32, "height" : 32, "paletteIndices" : "AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAABAQEBAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAQEBAQICAwMBAQAAAAAAAAAAAAAAAAAAAAAAAAAAAAEEBAQBAgIDAwMCAQABAQAAAAAAAAAAAAAAAAAAAAAAAQUFBAQBAgIDAgIBAQMBAAAAAAAAAAAAAAAAAAAAAAAAAQEFBAUBAgICAgIDAwEAAAAAAAAAAAAAAAAAAAAAAAABBgEFBQUBAgECAgIBAAAAAAAAAAAAAAAAAAAAAAAAAAEGBwEFBAUBCAEBAQEAAAAAAAAAAAAAAAAAAAAAAAAAAQgBBwEEBQEJAQEFBQEAAAAAAAAAAAAAAAAAAAAAAAEICAEHCAEEBQEBBQEBAAAAAAAAAAAAAAAAAAAAAAAAAAEGCQkGBgEBAQEBAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAEBBgYGAQIDAQAAAAAAAAAAAAAAAAAAAAAAAAAAAAABCQEBAQEBAQEHAQAAAAAAAAAAAAAAAAAAAAAAAAAAAQEBBwcDAgEKCgEBAAAAAAAAAAAAAAAAAAAAAAAAAAABAgIBAwMCAQkJAQEAAAAAAAAAAAAAAAAAAAAAAAAAAQEBAQIBAgMCAQEBCgEAAAAAAAAAAAAAAAAAAAAAAAABCwsKAQIBAQECAgEKAQAAAAAAAAAAAAAAAAAAAAAAAAABCwsKAQICAgIBCgoBAAAAAAAAAAAAAAAAAAAAAAAAAAABAQEBAQEBAQEBAQAAAAAAAAAAAAAAAAAAAAAAAAAAAQEBAQEBAQEBAQEBAAAAAAAAAAAAAAAAAAAAAAAAAAABAQEBAQEBAQEBAQEAAAAAAAAAAAAAAAAAAAAAAAAAAAABAQEBAQEBAQEBAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAQEBAQEBAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA==" - }, - "palette" : { - "originalArgb8888" : [ -14671840, -11431408, -9326048, -802016, -3964416, -5086944, -789517, -810399, -1863087, -10403552, -5078447 ], - "convertedRgb565" : [ 8452, 21634, 30084, -2556, -15360, -19708, -2146, -2804, -7030, 25092, -19446 ] } }, "diagnostics" : [ ] @@ -1540,14 +1540,14 @@ "last_modified" : 1775797786716, "fingerprint" : "6104ba7f216a937994d478ed07766ec28f48ad72fdd6620508535a1f877b8ddb", "metadata" : { + "palette" : { + "originalArgb8888" : [ -14671840, -11431408, -9326048, -802016, -3964416, -5086944, -789517, -810399, -1863087, -10403552, -5078447 ], + "convertedRgb565" : [ 8452, 21634, 30084, -2556, -15360, -19708, -2146, -2804, -7030, 25092, -19446 ] + }, "tile" : { "width" : 32, "height" : 32, "paletteIndices" : "AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAABAQEBAAAAAAEBAAAAAAAAAAAAAAAAAAAAAAAAAAEBAQICAwMBAQEBAwEAAAAAAAAAAAAAAAAAAAAAAAABBAQBAgIDAwMCAQMDAQAAAAAAAAAAAAAAAAAAAAAAAQUFBAQBAgIDAgICAwIBAAAAAAAAAAAAAAAAAAAAAAABBQEFBAUBAgICAgMCAQAAAAAAAAAAAAAAAAAAAAAAAAABBgEFBQUBAgECAgIBAAAAAAAAAAAAAAAAAAAAAAAAAAEGBwEFBAUBCAEBAQAAAAAAAAAAAAAAAAAAAAAAAAAAAQgBBwEEBQEJAQEAAAAAAAAAAAAAAAAAAAAAAAAAAAEICAEHCQEEBQEFAQAAAAAAAAAAAAAAAAAAAAAAAAAAAAEGCQkGBgEBAQEBAAAAAAAAAAAAAAAAAAAAAAAAAAABAQEBBgYGAQIDAgEBAAAAAAAAAAAAAAAAAAAAAAAAAAEJAQEBAQEBAgIBAQAAAAAAAAAAAAAAAAAAAAAAAAAAAAEBBwcDAgIBAQoKAQAAAAAAAAAAAAAAAAAAAAAAAAAAAQQBAwMDAgIBCQkBAAAAAAAAAAAAAAAAAAAAAAAAAAEBAgECAwMCAQEBAQEAAAAAAAAAAAAAAAAAAAAAAAABCwYBAgEBAQECAgEKAQAAAAAAAAAAAAAAAAAAAAAAAAELCgYBAgICAgEBAQEAAAAAAAAAAAAAAAAAAAAAAAAAAAEKCgoBAQEBAQEBAQAAAAAAAAAAAAAAAAAAAAAAAAAAAQEBAQEBAQEBAQEBAAAAAAAAAAAAAAAAAAAAAAAAAAAAAQEBAQEBAQEBAQAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAEBAQEBAQAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA==" - }, - "palette" : { - "originalArgb8888" : [ -14671840, -11431408, -9326048, -802016, -3964416, -5086944, -789517, -810399, -1863087, -10403552, -5078447 ], - "convertedRgb565" : [ 8452, 21634, 30084, -2556, -15360, -19708, -2146, -2804, -7030, 25092, -19446 ] } }, "diagnostics" : [ ] @@ -1602,14 +1602,14 @@ "last_modified" : 1776965154257, "fingerprint" : "8771c3e294d0edbc8dd3aaa6995a6db32166ae6bfb3e063170cc79b298d17e71", "metadata" : { + "palette" : { + "originalArgb8888" : [ -12019640 ], + "convertedRgb565" : [ 19657 ] + }, "tile" : { "width" : 8, "height" : 8, "paletteIndices" : "AQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQ==" - }, - "palette" : { - "originalArgb8888" : [ -12019640 ], - "convertedRgb565" : [ 19657 ] } }, "diagnostics" : [ ] @@ -1620,14 +1620,14 @@ "last_modified" : 1776965154257, "fingerprint" : "5d81eef8be13043330b42b546e10beed8ba00dfaa42df67477a8778c2b9484d7", "metadata" : { + "palette" : { + "originalArgb8888" : [ -12019640, -12552128, -14129088, -14133200, -14145496, -7835584, -5730208, -10465232 ], + "convertedRgb565" : [ 19657, 17352, 11080, 10950, 10565, -29816, -21364, 25222 ] + }, "tile" : { "width" : 8, "height" : 8, "paletteIndices" : "AQEBAQEBAQEBAQEBAQICAgECAgICAgICAgMEBQUFBQQDBAUGBgYGBQMEBQYGBwcIAwQFCAYGCAgBAwUFCAgIBw==" - }, - "palette" : { - "originalArgb8888" : [ -12019640, -12552128, -14129088, -14133200, -14145496, -7835584, -5730208, -10465232 ], - "convertedRgb565" : [ 19657, 17352, 11080, 10950, 10565, -29816, -21364, 25222 ] } }, "diagnostics" : [ ] @@ -1638,14 +1638,14 @@ "last_modified" : 1776965154258, "fingerprint" : "3250840c4fe08c134ea966ce7c8fcaccae2c2a45660d7173c5e262a2e5076548", "metadata" : { + "palette" : { + "originalArgb8888" : [ -12552128, -14133200, -14145496, -10465232, -5730208, -7835584 ], + "convertedRgb565" : [ 17352, 10950, 10565, 25222, -21364, -29816 ] + }, "tile" : { "width" : 8, "height" : 8, "paletteIndices" : "AQEBAQECAwMBAQEBAgMEBQEBAQIDBAUFAQIDAwQEBAQDAwYFBQUFBQQGBQUGBgYGBQUFBgYFBQUFBgYGBQUGBg==" - }, - "palette" : { - "originalArgb8888" : [ -12552128, -14133200, -14145496, -10465232, -5730208, -7835584 ], - "convertedRgb565" : [ 17352, 10950, 10565, 25222, -21364, -29816 ] } }, "diagnostics" : [ ] @@ -1656,14 +1656,14 @@ "last_modified" : 1776965154258, "fingerprint" : "fe3ab2b7eb3b10a042de14484d53e718e6b505edb1ad19053668565bfe3a8f25", "metadata" : { + "palette" : { + "originalArgb8888" : [ -14145496, -14133200, -12552128, -5730208, -10465232, -7835584 ], + "convertedRgb565" : [ 10565, 10950, 17352, -21364, 25222, -29816 ] + }, "tile" : { "width" : 8, "height" : 8, "paletteIndices" : "AQECAwMDAwMEBQECAwMDAwQEBQECAwMDBQUFBQEBAgMEBAQEBAYBAQYGBgYEBAYFBAQEBgYEBAQGBgQEBgYGBA==" - }, - "palette" : { - "originalArgb8888" : [ -14145496, -14133200, -12552128, -5730208, -10465232, -7835584 ], - "convertedRgb565" : [ 10565, 10950, 17352, -21364, 25222, -29816 ] } }, "diagnostics" : [ ] @@ -1674,14 +1674,14 @@ "last_modified" : 1776965154259, "fingerprint" : "7fcbf90e1e9a69d6ce3be80ea1901d66c9992f68dc72e4c636dcd2ad52fa2898", "metadata" : { + "palette" : { + "originalArgb8888" : [ -12019640, -12552128, -14133200, -14145496, -14129088, -7835584, -10465232, -5730208 ], + "convertedRgb565" : [ 19657, 17352, 10950, 10565, 11080, -29816, 25222, -21364 ] + }, "tile" : { "width" : 8, "height" : 8, "paletteIndices" : "AQEBAQEBAQECAgIBAQEBAQICAgICAgIBAwQEBAQDBQIEBgYGBgQDBQcICAYGBAMFBwcGBgcEAwUIBwcHBAQFAQ==" - }, - "palette" : { - "originalArgb8888" : [ -12019640, -12552128, -14133200, -14145496, -14129088, -7835584, -10465232, -5730208 ], - "convertedRgb565" : [ 19657, 17352, 10950, 10565, 11080, -29816, 25222, -21364 ] } }, "diagnostics" : [ ] @@ -1692,14 +1692,14 @@ "last_modified" : 1776965154259, "fingerprint" : "451fc8d646049944d5aa7c7dc254636eec0151aaff6e2051059304b9d6ebc31e", "metadata" : { + "palette" : { + "originalArgb8888" : [ -12019640, -14129088, -14133200, -14145496, -10465232, -5730208, -7835584 ], + "convertedRgb565" : [ 19657, 11080, 10950, 10565, 25222, -21364, -29816 ] + }, "tile" : { "width" : 8, "height" : 8, "paletteIndices" : "AQIDBAQFBgYBAQIDBAYGBwEBAQMEBgcHAQEBBAQGBwcBAQQFBAYHBwEEBwUEBgcHBAcGBQQGBwcEBwYFBAYHBw==" - }, - "palette" : { - "originalArgb8888" : [ -12019640, -14129088, -14133200, -14145496, -10465232, -5730208, -7835584 ], - "convertedRgb565" : [ 19657, 11080, 10950, 10565, 25222, -21364, -29816 ] } }, "diagnostics" : [ ] @@ -1710,14 +1710,14 @@ "last_modified" : 1776965154260, "fingerprint" : "aa757df4600823ec6655235a1081061777124ccee74b31481bbe402e53635f53", "metadata" : { + "palette" : { + "originalArgb8888" : [ -7835584, -5730208, -10465232, -14145496 ], + "convertedRgb565" : [ -29816, -21364, 25222, 10565 ] + }, "tile" : { "width" : 8, "height" : 8, "paletteIndices" : "AQECAwMBAQEBAgIBAwMBAgICAQEBAwMCAgIBAQIDBAMCAgEBAgMEBAICAQECAwQEAgIBAQIDBAMCAgIBAwQDAg==" - }, - "palette" : { - "originalArgb8888" : [ -7835584, -5730208, -10465232, -14145496 ], - "convertedRgb565" : [ -29816, -21364, 25222, 10565 ] } }, "diagnostics" : [ ] @@ -1728,14 +1728,14 @@ "last_modified" : 1776965154260, "fingerprint" : "38162157f5685cce25b835d3a2caee3465fd2ec3ee5db2a5089d7d5ae5ea3bb7", "metadata" : { + "palette" : { + "originalArgb8888" : [ -7835584, -10465232, -5730208, -14145496 ], + "convertedRgb565" : [ -29816, 25222, -21364, 10565 ] + }, "tile" : { "width" : 8, "height" : 8, "paletteIndices" : "AQEBAgIDAQEDAQICAQMDAQMCAgEBAQMDAgQCAwEBAwMEBAIDAQEDAwQEAgMBAQMDAgQCAwEBAwMDAgQCAQMDAw==" - }, - "palette" : { - "originalArgb8888" : [ -7835584, -10465232, -5730208, -14145496 ], - "convertedRgb565" : [ -29816, 25222, -21364, 10565 ] } }, "diagnostics" : [ ] @@ -1746,14 +1746,14 @@ "last_modified" : 1776965154260, "fingerprint" : "8cab5b3d553af9ed371bd19fc624763accc90e5d926d300ba31dd8d9d6bab803", "metadata" : { + "palette" : { + "originalArgb8888" : [ -5730208, -10465232, -14145496, -14133200, -14129088, -12019640, -7835584 ], + "convertedRgb565" : [ -21364, 25222, 10565, 10950, 11080, 19657, -29816 ] + }, "tile" : { "width" : 8, "height" : 8, "paletteIndices" : "AQECAwMEBQYHAQEDBAUGBgcHAQMEBgYGBwcBAwMGBgYHBwEDAgMGBgcHAQMCBwMGBwcBAwIBBwMHBwEDAgEHAw==" - }, - "palette" : { - "originalArgb8888" : [ -5730208, -10465232, -14145496, -14133200, -14129088, -12019640, -7835584 ], - "convertedRgb565" : [ -21364, 25222, 10565, 10950, 11080, 19657, -29816 ] } }, "diagnostics" : [ ] @@ -1764,14 +1764,14 @@ "last_modified" : 1776965154261, "fingerprint" : "d9ff5a6df0f65f5fcfb8f22376beeb266d429e2c6e9c82f51c12bc6ee4c3fcdc", "metadata" : { + "palette" : { + "originalArgb8888" : [ -14145496, -10465232, -7835584, -5730208, -14133200, -14129088, -12019640 ], + "convertedRgb565" : [ 10565, 25222, -29816, -21364, 10950, 11080, 19657 ] + }, "tile" : { "width" : 8, "height" : 8, "paletteIndices" : "AQIDAgIBBAMFAQECAgEEBAUGBQECAgEEBwYFBQECAQEHBwYGBQEBAgcHBwYFAQMDBwcHBwEBAwMHBwcFAQICAw==" - }, - "palette" : { - "originalArgb8888" : [ -14145496, -10465232, -7835584, -5730208, -14133200, -14129088, -12019640 ], - "convertedRgb565" : [ 10565, 25222, -29816, -21364, 10950, 11080, 19657 ] } }, "diagnostics" : [ ] @@ -1782,14 +1782,14 @@ "last_modified" : 1776965154261, "fingerprint" : "b9ff45c77f7779a6acebcc537c2ddac0e27e91162b656a04dc4772ec5f24fc26", "metadata" : { + "palette" : { + "originalArgb8888" : [ -7835584, -5730208, -10465232, -14145496 ], + "convertedRgb565" : [ -29816, -21364, 25222, 10565 ] + }, "tile" : { "width" : 8, "height" : 8, "paletteIndices" : "AQICAwMBAQIBAQMDAgIBAQIBAQEBAgIBAgICAgEBAgIEAwMCAgEBAQMEAwMCAgEBAQMEAwMDAgIBAwMEAwMDAw==" - }, - "palette" : { - "originalArgb8888" : [ -7835584, -5730208, -10465232, -14145496 ], - "convertedRgb565" : [ -29816, -21364, 25222, 10565 ] } }, "diagnostics" : [ ] @@ -1800,14 +1800,14 @@ "last_modified" : 1776965154261, "fingerprint" : "43f370324fedccda888d49409e2a64f182f08b4143b4bdd5bafaf498feebd21a", "metadata" : { + "palette" : { + "originalArgb8888" : [ -5730208, -7835584, -10465232, -14145496 ], + "convertedRgb565" : [ -21364, -29816, 25222, 10565 ] + }, "tile" : { "width" : 8, "height" : 8, "paletteIndices" : "AQICAwMBAQICAgEBAwMCAgIBAQICAgIBAQECAgEBAQECAgIBAQMDBAICAQEDAwQDAQEDAwMEAwIDAwMDBAMDAg==" - }, - "palette" : { - "originalArgb8888" : [ -5730208, -7835584, -10465232, -14145496 ], - "convertedRgb565" : [ -21364, -29816, 25222, 10565 ] } }, "diagnostics" : [ ] @@ -1818,14 +1818,14 @@ "last_modified" : 1776965154262, "fingerprint" : "cb047e655f4e196f22ca0048149df5dcb959f895faeaeb94920182d4a2d16b38", "metadata" : { + "palette" : { + "originalArgb8888" : [ -7835584, -5730208, -14145496, -10465232, -14133200, -14129088, -12019640 ], + "convertedRgb565" : [ -29816, -21364, 10565, 25222, 10950, 11080, 19657 ] + }, "tile" : { "width" : 8, "height" : 8, "paletteIndices" : "AQIDBAQBBAMCAgMEBAMDBQIDBAQDBQYFAwMEAwUFBgcEAwMFBgYHBwEBAwUGBwcHAQEDAwcHBwcBBAQDBQcHBw==" - }, - "palette" : { - "originalArgb8888" : [ -7835584, -5730208, -14145496, -10465232, -14133200, -14129088, -12019640 ], - "convertedRgb565" : [ -29816, -21364, 10565, 25222, 10950, 11080, 19657 ] } }, "diagnostics" : [ ] @@ -1836,14 +1836,14 @@ "last_modified" : 1776965154262, "fingerprint" : "25eba17b67dd5159f5fb9d3edd531d54a44d1c76f997385840dac53517b98886", "metadata" : { + "palette" : { + "originalArgb8888" : [ -12019640, -14145496, -7835584, -10465232, -14133200, -14129088 ], + "convertedRgb565" : [ 19657, 10565, -29816, 25222, 10950, 11080 ] + }, "tile" : { "width" : 8, "height" : 8, "paletteIndices" : "AQEBAgMDBAQBAQIDAwMDBAEBAgMDAwMEAQECAwMEAgQBAQIEAgUFAgEBBQUGBQYFAQEBAQEGAQYBAQEBAQEBAQ==" - }, - "palette" : { - "originalArgb8888" : [ -12019640, -14145496, -7835584, -10465232, -14133200, -14129088 ], - "convertedRgb565" : [ 19657, 10565, -29816, 25222, 10950, 11080 ] } }, "diagnostics" : [ ] @@ -1854,14 +1854,14 @@ "last_modified" : 1776965154262, "fingerprint" : "32ca96c14290de8009fd2db623f55514bed2345b7d5881a80dd3fe6235012854", "metadata" : { + "palette" : { + "originalArgb8888" : [ -10465232, -14145496, -14133200, -7835584, -14129088, -12019640 ], + "convertedRgb565" : [ 25222, 10565, 10950, -29816, 11080, 19657 ] + }, "tile" : { "width" : 8, "height" : 8, "paletteIndices" : "AQEBAgEBAgICAQICAQIBAQICAwICAQEEAgMDAwIBAQQDAwUDAwIBAQUFBgUFAgEEBgYGBgYDAgEGBgYGBgYDAg==" - }, - "palette" : { - "originalArgb8888" : [ -10465232, -14145496, -14133200, -7835584, -14129088, -12019640 ], - "convertedRgb565" : [ 25222, 10565, 10950, -29816, 11080, 19657 ] } }, "diagnostics" : [ ] @@ -1872,14 +1872,14 @@ "last_modified" : 1776965154263, "fingerprint" : "7a093fe00c805bcf38d4facff14a6d4c2b8baeaa2d553fa8d3db9f2d76b32f3b", "metadata" : { + "palette" : { + "originalArgb8888" : [ -14145496, -10465232, -7835584, -14133200, -14129088, -12019640 ], + "convertedRgb565" : [ 10565, 25222, -29816, 10950, 11080, 19657 ] + }, "tile" : { "width" : 8, "height" : 8, "paletteIndices" : "AQECAgECAgICAgECAQECAQMCAgEBBAEBAwICAQQEBAECAgEEBAUEBAMCAQUFBgUFAgEEBgYGBgYBBAYGBgYGBg==" - }, - "palette" : { - "originalArgb8888" : [ -14145496, -10465232, -7835584, -14133200, -14129088, -12019640 ], - "convertedRgb565" : [ 10565, 25222, -29816, 10950, 11080, 19657 ] } }, "diagnostics" : [ ] @@ -1890,14 +1890,14 @@ "last_modified" : 1776965154263, "fingerprint" : "77c5277220421226d16f58b1bcfb4eaf157fa4f6c740c5aaebefaf88fb91c22e", "metadata" : { + "palette" : { + "originalArgb8888" : [ -10465232, -7835584, -14145496, -12019640, -14133200, -14129088 ], + "convertedRgb565" : [ 25222, -29816, 10565, 19657, 10950, 11080 ] + }, "tile" : { "width" : 8, "height" : 8, "paletteIndices" : "AQECAgMEBAQBAgICAgMEBAECAgICAwQEAQMBAgIDBAQDBQUDAQMEBAUGBQYFBQQEBgQGBAQEBAQEBAQEBAQEBA==" - }, - "palette" : { - "originalArgb8888" : [ -10465232, -7835584, -14145496, -12019640, -14133200, -14129088 ], - "convertedRgb565" : [ 25222, -29816, 10565, 19657, 10950, 11080 ] } }, "diagnostics" : [ ] @@ -1909,7 +1909,7 @@ "relative_path" : "scene-bank.pack-request.json", "mime_type" : "application/json", "size" : 1313159, - "last_modified" : 1777631167251, + "last_modified" : 1778159580103, "fingerprint" : "31b7a0019dc08d84af95893b349839ba2975e0f8094d8eafdc1b4c48841709f8", "metadata" : { "scenePackRequest" : { diff --git a/tools/vscode-extension/.gitignore b/tools/vscode-extension/.gitignore index ab554d4a..12ee8905 100644 --- a/tools/vscode-extension/.gitignore +++ b/tools/vscode-extension/.gitignore @@ -32,4 +32,7 @@ Thumbs.db # Editor local state .vscode/settings.json -.vscode/*.log \ No newline at end of file +.vscode/*.log + +# AI +debug \ No newline at end of file -- 2.47.2