Underground 2 Revived
Play Need for Speed: Underground 2 (2004) in Chrome and Firefox with WebGPU graphics, Web Audio, up to 120 fps widescreen, controller support, free roam and Online races with friends. Fan project, not
翻译准备中
FPS satírico de navegador: 5 facções brasileiras caricatas, 44 personagens, 5 mapas e 26 armas — rounds e Capture the Flag contra bots, direto na aba, sem instalar nada. Three.js + vanilla JS, zero build. Gerado em par com agentes de IA (Claude, Kimi, Codex/GPT, GLM) — AI generated & AI friendly.
翻译准备中
取自仓库 README
正在加载完整 README。 以下为已保存的摘录。
AI generated & AI friendly — construído em par com agentes de IA, e cada commit diz qual escreveu (trailer Agent:, convenção em CONTRIBUTING.md): FPS gratuito de navegador em Three.js: 5 facções brasileiras caricatas, 44 personagens originais, 5 mapas satíricos e 26 armas — rounds e Capture the Flag contra bots, direto na aba. Sem download, sem instalação, sem cadastro.查看完整 README ↗
AI generated & AI friendly — construído em par com agentes de IA, e cada
commit diz qual escreveu (trailer Agent:, convenção em CONTRIBUTING.md):
FPS gratuito de navegador em Three.js: facções brasileiras caricatas, personagens originais, mapas satíricos e armas. Partidas contra bots e multiplayer beta, direto na aba. Sem download ou instalação para jogar.
| O que | Quanto | Onde confere |
|---|---|---|
| Código do jogo | 67.475 linhas em 163 arquivos | git ls-files public/js/*.js | xargs wc -l |
game.js | 9.062 linhas | wc -l public/js/game.js |
main.js | 5.300 linhas | wc -l public/js/main.js |
| Armas com GLB | 27 | git ls-files 'public/models/weapons/*.glb' | wc -l |
| GLBs de personagem | 74 | git ls-files 'public/models/characters/*.glb' | wc -l |
| Props em GLB | 217 | git ls-files 'public/models/props/*.glb' | wc -l |
| Clipes de animação versionados | 897 | git ls-files public/models/anims | wc -l |
| Personagens jogáveis | 63, em 7 grupos | array CHARACTERS de characters.js |
| Mapas no menu | 12 | MAPS menos MAPAS_PARADOS |
| Arnêses visuais em HTML | 25 | git ls-files 'public/*.html' | wc -l |
| Scripts do arnês | 891 | git ls-files 'tools/eval/*.mjs' 'tools/eval/*.py' | wc -l |
| Scripts de pipeline | 120 | git ls-files 'tools/*.mjs' | wc -l |
| Tarefas de entrada escritas | 26 | git ls-files 'docs/issues/[0-9]*.md' | wc -l |
| Versão | 2.1.0-alpha.128 | public/js/version.js e package.json (batem) |
Bloco gerado por
node tools/gen-docs.mjs. Fonte:o comando da coluna direita de cada linha
O multiplayer está em beta. O cliente de rede vive em
public/js/net.js, com os transportes empublic/js/transporte.js— salas públicas e privadas por código de convite saem do mesmo cliente. Para testar o jogo local sem configurar um servidor multiplayer, comece pelo modo singleplayer. No celular há beta instalável como PWA com controles de toque (public/site.webmanifest).
▶ Jogue: https://www.corosolto.com.br/
O jogo já se chamou CS BRASIL. É o mesmo jogo, e o nome antigo segue registrado como nome alternativo pra quem procura por ele.
Este jogo nasceu gerado por IA a partir de um único prompt — o prompt original está em
docs/historico/PROMPT.md.
| Você é… | Leia |
|---|---|
| curioso | esta página, e depois https://www.corosolto.com.br/ |
| dev novo (ou agente) | docs/README.md → CONTRIBUTING.md |
| quer entender a stack | docs/docs/stack.md — Three.js, Astro, Supabase, geração de asset, skills |
| quer contribuir hoje | issues abertas e CONTRIBUTING.md; confira o estado antes de escolher |
| quer saber o que está quebrado | as issues abertas |
Site de documentação (Docusaurus, com instrumentação de IA, quality gates e
arquitetura): cd docs && npm install && npm start → http://localhost:3000/docs/.
| Camada | Ferramenta | Versão |
|---|---|---|
| Motor 3D (WebGL) | Three.js, vendorizado | r160 |
| Jogo | ES modules vanilla, zero build | 163 arquivos |
| Site | Astro com SSR | ^7.1.1 |
| Hospedagem | adapter Vercel | ^11.0.6 |
| Banco | Postgres gerenciado (RLS; schema privado, fora do repo) | ^2.110.7 |
| Browser nas réguas | Playwright | ^1.62.1 |
| Pipeline de GLB | gltf-transform | ^4.4.1 |
| Compressão de malha | meshoptimizer | ^1.2.0 |
| Imagem (build e API) | sharp · resvg | ^0.35.3 · ^2.6.2 |
| Esta documentação | Docusaurus | 3.10.2 |
| Runtime de CI | Node | 22 |
Three.js sai de public/vendor/three.module.js (sem CDN, sem npm no runtime). Astro e Vercel de package.json + astro.config.mjs + vercel.json. Dos scripts de tools/, 305 importam Playwright, 125 importam gltf-transform e 14 importam meshoptimizer.
Bloco gerado por
node tools/gen-docs.mjs. Fonte:dependencies/devDependencies do package.json · REVISION de public/vendor/three.module.js
O detalhe de cada uma — por que o jogo não tem build, como o asset é gerado (mint.gg, Tripo3D, Meshy, OpenRouter), o que Playwright e gltf-transform fazem aqui, e o que são as skills de agente — está em Stack e ferramentas.
Um repositório, duas zonas com regras diferentes:
public/ · JavaScript vanilla com ES modules, Three.js
vendorizado em public/vendor/ (a revisão está na tabela de stack acima),
zero build. Nunca vira framework.
Não existe public/index.html: o HTML do jogo é src/pages/index.astro,
servido na rota /. (Este README já afirmou o contrário por meses e mandava
todo dev novo para o arquivo errado.)src/ · Astro com SSR na Vercel. Landing,
ranking global, perfis públicos, páginas de conteúdo e as rotas /api/*. Aqui
framework é bem-vindo — mas o jogo continua intocado.O ranking e a telemetria vivem num Postgres gerenciado (schema privado, fora do repo) — o ranking está
desligado por flag hoje, a coleta não parou (ver a seção abaixo). A
service_role key fica só no servidor; a anon key é pública por design, e a
segurança vem das policies e dos grants por coluna.
Sem contagem na árvore abaixo — os números vivem no bloco gerado lá em cima.
Índice por número escrito à mão desatualiza no primeiro commit; é a mesma razão
de o tools/eval/ARCH.md ser gerado.
STATUS.md estado de hoje (leia primeiro)
astro.config.mjs Astro + adapter Vercel · `site` COM www (canonical)
vercel.json build, headers de segurança (CSP…) e cache
src/
layouts/Layout.astro shell do site: nav, footer, CSS global, JSON-LD base
lib/site.ts nome, host, descrições e @id de JSON-LD (fonte única)
lib/supabase.ts client admin (service_role, só no servidor)
lib/safe-url.ts allowlist de avatar + fetch com trava de SSRF
lib/ratelimit.ts rate limit durável (contado no Postgres)
data/jogo.ts armas/mapas/personagens em forma de dado, pro site
pages/index.astro O JOGO, na rota `/`
pages/ranking.astro leaderboard (SSR, com cache de CDN)
pages/u/[...path] perfil público por jogador + badge PNG
pages/sitemap.xml.ts sitemap dinâmico, cobre os perfis
pages/api/* register, submit-match, leaderboard, badge, avatar…
public/ O JOGO (vanilla, zero build)
js/ vendor/ models/ style.css robots.txt llms.txt og-image.png
audio/ ⚠ NÃO versionado — ver "Áudio" abaixo
tools/ pipeline de asset (gen-asset, gen-image, otimização de GLB)
gen-arch.mjs GERA tools/eval/ARCH.md (índice + tabela de conflito)
gen-docs.mjs GERA os blocos numéricos deste README e de docs/
tools/eval/ o arnês de medição e os quality gates de qualidade
docs/ documentação para devs (Docusaurus) + as issues de entrada
.agents/skills/ skills de agente (.claude/skills/ são symlinks pra cá)
Duas pastas NÃO vêm no clone, por decisão registrada: public/audio/ (direitos
incertos) e references/ (telas-alvo da UI e frames de referência, que ficam só na
máquina do dono). O que sobrevive das references/ são os números medidos:
tools/eval/ref_ui.json e tools/eval/ref_viewmodel.json, esses versionados. Régua que
precisa rodar em CI lê o JSON, nunca o PNG.
O site completo (é o modo que você quer — inclui o jogo):
git clone https://github.com/corosolto/client.git
cd client
npm ci
npm run fetch-audio # opcional: sem o pacote, o jogo usa sons sintetizados
npm run dev # http://localhost:4321 — o jogo está em /
Use Node/npm compatíveis com os engines do package-lock.json, incluindo Astro e
suas dependências. A instalação foi conferida em 10/10/2026 com Node 23.6.0 e npm 11.6.0.
Confira node --version e npm --version no mesmo terminal antes de instalar.
Build e preview:
npm run build # gera dist/ (client + server)
npm run preview # serve dist/client estaticamente
python3 -m http.server -d public serve só os assets do jogo — o HTML não
está lá. Use npm run dev.
Comandos atuais do quality gate: veja o bloco gerado no AGENTS.md e em docs/docs/comecando.md.
npm run arch # regenera tools/eval/ARCH.md (índice + tabela de conflito)
npm run docs # regenera os blocos numéricos deste README e de docs/
Nada commita com invariante vermelha. O catálogo do arnês está em
tools/eval/README.md.
Documentação que carrega número é gerada. npm run docs:check (dentro do
check:fast) reprova quando um bloco gerado diverge do código — foi assim que
uma linha afirmando "game.js tem 3.234 linhas" sobreviveu até o arquivo
dobrar de tamanho.
npm run eval:vmenpm run eval:invariantsleem GLBs depublic/models/. Numa árvore sem os assets baixados, os dois falham comENOENT— é ambiente, não regressão.
O repo agora inclui integração project-scoped do Graphify para múltiplos adapters:
agent skills via .agents/Arquivos principais:
AGENTS.md e CLAUDE.md: instruções de uso do grafo.codex/, .claude/, .opencode/, .kimi/, .agents/: skills/config por adaptergraphify-out/graph.json: grafo consultávelgraphify-out/GRAPH_REPORT.md: resumo navegávelgraphify-out/graph.html: visualização local do grafoBuild inicial do grafo:
code-only, local e determinísticoAtualizar depois de mudanças de código:
./scripts/graphify update .
./scripts/graphify cluster-only . --graph ./graphify-out/graph.json --no-label
Regenerar do zero:
./scripts/graphify extract . --code-only --out . --force
./scripts/graphify cluster-only . --graph ./graphify-out/graph.json --no-label
Observação: a versão atual do Graphify extrai este repo muito bem em JS/TS/SQL, mas ainda
reporta parsing parcial em arquivos .astro. Isso é limitação do extrator atual, não do
projeto.
| Tecla | Ação |
|---|---|
| W A S D | Mover |
| Mouse | Mirar |
| Shift | Correr |
| Ctrl ou C | Agachar — mira bem mais estável |
| Espaço | Pular |
| Clique esq. | Atirar |
| Clique dir. | Luneta / ADS |
| R | Recarregar |
| 1 / 2 / 3 | Primária / pistola / faca |
| Z / X / V | Rádio estilo CS (comandos de voz) |
| M | Trocar de time (a qualquer momento) |
| Tab | Placar |
| Esc | Pausar |
Regras, lidas das constantes de public/js/game.js:
| Regra | Valor | Constante |
|---|---|---|
| Grupos · personagens | 7 · 63 (B 9 · C 9 · E 8 · F 9 · M 9 · P 10 · U 9) | CHARACTERS |
| Mapas no menu | 12 — 2 abrem em rodadas, 10 em captura | MAPS menos MAPAS_PARADOS |
| Respawn | 2,2 s | RESPAWN_DELAY |
| Round | 99 s, 3 vitórias | ROUND_TIME / ROUNDS_TO_WIN |
| Captura | alvo = todas as bandeiras do mapa, 2 rodadas (rede de segurança 480 s) | capsToWin = ctfPts.length / CTF_ROUNDS_TO_WIN |
| Regeneração de vida | DESLIGADA — ?regen=1 religa | REGEN |
Ranking / páginas /u/ | DESLIGADOS — é uma flag, volta numa linha | RANKING_ON em src/lib/site.ts |
Bloco gerado por
node tools/gen-docs.mjs. Fonte:constantes de public/js/game.js · RANKING_ON de src/lib/site.ts
O menu aceita de 1 a 8 bots por lado (settings.bots); o padrão é 4×4. O time
com mais abates leva o round. AWP mata com um tiro em qualquer lugar do corpo.
Multikills disparam anúncios estilo Unreal Tournament.
Regeneração de vida está DESLIGADA (decisão do dono, 05/08/2026): vida só
volta com respawn. ?regen=1 religa a regra antiga — inteira, com a simetria
jogador↔bot. Ela foi desligada porque era invisível: sem ícone, sem som e
sem linha nas configurações, e regra que o jogador não percebe é
indistinguível de defeito.
Os mapas registrados, e em que modo cada um abre:
| Id | Nome no menu | Abre em | Arquivo em public/js/ | Linhas |
|---|---|---|---|---|
amazonia | Treta na Amazônia | captura | — | — |
escadao | Escadão (Morro) | captura | — | — |
praca_poderes | Praça dos Três Poderes | rodadas | — | — |
piscina_treta | Piscina da Treta | rodadas | — | — |
loja_h | Loja H (Estacionamento) | captura | — | — |
ferro_velho | Ferro Velho do Zé | captura | — | — |
quebrada | Quebrada (Rua do Baile) | captura | — | — |
corrego | Córrego (Favela de SP) | captura | — | — |
lajes | Lajes (Comunidade) | captura | — | — |
posto_treta | Posto da Treta | captura | — | — |
upa_24h | UPA 24h da Treta | captura | — | — |
velho_oeste | Sertão da Treta | captura | — | — |
12 mapas no menu — 2 abrem em rodadas e 10 em captura. ctfMode abre o mapa em captura, não prende: o jogador troca no menu (é a MOD1). Há 24 arquivos map_*.js em public/js/; mapas em MAPAS_PARADOS ficam fora do menu.
Bloco gerado por
node tools/gen-docs.mjs. Fonte:objeto MAPS menos MAPAS_PARADOS de public/js/maps.js
RANKING_ON = false em src/lib/site.ts. Decisão do dono em
04/08/2026: "vamos desabilitar o ranking por enquanto, depois a gente ajeita".
O motivo é o de sempre nesta base — o modelo é client-authoritative, o placar
é forjável, e publicar classificação forjável é publicar número errado.
É flag, não remoção. Com false:
/ranking e /u/* respondem 200 com aviso + noindex — não 404. As URLs
estão indexadas e vão voltar no mesmo endereço;/api/leaderboard responde {disabled:true}; o cliente não conhece a flag,
ele reage à resposta da API. Uma fonte de verdade, no servidor.O que NÃO parou: a coleta. submit_match continua gravando (valida token,
rate limit por nick/IP/dia, tetos absolutos e consistência física) e a telemetria
nova continua medindo. Quando o ranking voltar, o histórico está lá.
docs/seguranca.mdA correção definitiva é o servidor de jogo escrever com service_role e o RLS
bloquear o cliente; está na fila junto do multiplayer.
public/audio/)A pasta não é versionada: as vozes e memes têm direitos incertos, e o repositório público leva só o código. Sem o pacote, o jogo usa sons sintetizados e funciona normalmente.
npm run fetch-audio # ou: AUDIO_PACK_URL=<zip> bash scripts/fetch-audio.sh
O jogo carrega audio/manifest.json (veja audio/manifest.example.json, esse
sim versionado). Samples originais do CS 1.6 são propriedade da Valve e não
são distribuídos aqui.
site com www no astro.config.mjs — todo canonical sai daí/sitemap.xml dinâmico, cobrindo uma URL por jogadorpublic/robots.txt e public/llms.txtVideoGame com @id estável, mais ItemList,
ProfilePage/Person, HowTo, FAQPage e BreadcrumbList por páginaCache-Control de CDN em /ranking, /u/* e /mapaO código está sob AGPL-3.0 (GNU Affero General Public License, versão 3) — é o que vale hoje, e a fonte é o arquivo LICENSE na raiz do repositório. Nenhum outro arquivo tem autoridade sobre isso.
Bloco gerado por
node tools/gen-docs.mjs. Fonte:título lido do texto do LICENSE, conferido contra o campo license do package.json
Migrado de MIT para AGPL-3.0 em 07/08/2026. As contribuições feitas antes da troca entraram sob MIT — licença permissiva e compatível com a AGPL: elas continuam MIT dentro do todo, e o conjunto é distribuído sob AGPL-3.0. Quem contribuiu antes não perde nada nem precisa de novo consentimento (a direção incompatível seria a inversa).
public/vendor/.Feito para rir, não para brigar.