feat(city): implement marketplace, missions, customization and admin dashboard
- Add database migrations for market_listings, missions and character cosmetics - Create controllers for marketplace, missions, presence and character customization - Implement admin world dashboard with live platform metrics - Add feature tests for world functionality - Include phase 2 design documents and gap analysis
This commit is contained in:
@@ -0,0 +1,60 @@
|
||||
<div style="text-align:center;margin-bottom:1.5rem">
|
||||
<h2>🏙️ City10 — Visão da Cidade 3D</h2>
|
||||
<p class="subtitle">Fase 2: Transformar o grid atual em uma cidade viva com ruas, árvores, prédios variados e atmosfera</p>
|
||||
</div>
|
||||
|
||||
<div class="section">
|
||||
<h3>O que já existe hoje</h3>
|
||||
<ul>
|
||||
<li>Chão verde com grid</li>
|
||||
<li>Caixas coloridas representando lojas</li>
|
||||
<li>Cápsulas amarelas para agentes</li>
|
||||
<li>Órbita de câmera, zoom, clique para selecionar</li>
|
||||
</ul>
|
||||
</div>
|
||||
|
||||
<div class="section">
|
||||
<h3>O que vamos adicionar</h3>
|
||||
<ul>
|
||||
<li><strong>Ruas asfaltadas</strong> com calçadas e marcações de trânsito</li>
|
||||
<li><strong>Quadras/blocos</strong> com prédios de fachada variada</li>
|
||||
<li><strong>Árvores, postes, bancos, floreiras</strong> — objetos de cena</li>
|
||||
<li><strong>Prédios residenciais/comerciais</strong> de preenchimento entre as lojas</li>
|
||||
<li><strong>Ciclo dia/noite</strong> com iluminação dinâmica</li>
|
||||
<li><strong>Mini-mapa</strong> no canto da tela</li>
|
||||
</ul>
|
||||
</div>
|
||||
|
||||
<hr style="border-color:var(--border);margin:1.5rem 0">
|
||||
|
||||
<h2 style="text-align:center">Layout da Cidade</h2>
|
||||
<p class="subtitle">Três abordagens para organizar ruas e quarteirões</p>
|
||||
|
||||
<div class="options" style="margin-top:1rem">
|
||||
<div class="option" data-choice="grid" onclick="toggleSelect(this)">
|
||||
<div class="letter">A</div>
|
||||
<div class="content">
|
||||
<h3>Grid Clássico</h3>
|
||||
<p>Ruas formando quadras regulares. Lojas em posições fixas nas esquinas e frentes. Fácil de navegar, previsível, urbano.</p>
|
||||
<p style="color:var(--muted);font-size:.85rem;margin-top:.5rem">✅ Mais simples de gerar, orientação clara</p>
|
||||
</div>
|
||||
</div>
|
||||
<div class="option" data-choice="organic" onclick="toggleSelect(this)">
|
||||
<div class="letter">B</div>
|
||||
<div class="content">
|
||||
<h3>Orgânico</h3>
|
||||
<p>Ruas curvas que conectam as lojas existentes. Praça central como ponto focal. Visual mais natural e europeu.</p>
|
||||
<p style="color:var(--muted);font-size:.85rem;margin-top:.5rem">✅ Mais bonito, ❌ Mais complexo de gerar</p>
|
||||
</div>
|
||||
</div>
|
||||
<div class="option" data-choice="hybrid" onclick="toggleSelect(this)">
|
||||
<div class="letter">C</div>
|
||||
<div class="content">
|
||||
<h3>Misto (Recomendado)</h3>
|
||||
<p>Grid base com quarteirões de tamanhos variados, praça central, algumas vias diagonais. Combina organização com personalidade.</p>
|
||||
<p style="color:var(--muted);font-size:.85rem;margin-top:.5rem">✅ 👍 Melhor equilíbrio entre beleza e implementação</p>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<p style="margin-top:1.5rem;text-align:center;color:var(--muted)">Clique na sua opção preferida e me diga no terminal se quer ajustar algo.</p>
|
||||
@@ -0,0 +1,77 @@
|
||||
<div style="text-align:center;margin-bottom:1.5rem">
|
||||
<h2>📐 Design — Cidade 3D Fase 2</h2>
|
||||
<p class="subtitle">Arquitetura, componentes, fluxo de dados e testes — revise seção por seção</p>
|
||||
</div>
|
||||
|
||||
<div class="section">
|
||||
<span class="label">1. Arquitetura</span>
|
||||
<p>A cena Three.js passa de <strong>órbita isométrica</strong> para <strong>exploração a pé</strong>. O backend continua o mesmo (Sanctum + <code>/city/data</code>), mas o payload ganha: ruas, prédios gerados, e um streaming de mensagens de chat via <strong>SSE</strong> (Server-Sent Events) por agente — sem dependência nova.</p>
|
||||
<pre style="background:#0b1220;border:1px solid var(--border);border-radius:.5rem;padding:.75rem;overflow:auto;font-size:.8rem">Frontend (Three.js)
|
||||
├── CameraController — WASD + mouse, colisão AABB
|
||||
├── CityGenerator — ruas, quadras, prédios de preenchimento
|
||||
├── CharacterFactory — carrega modelos GLTF por tipo de agente
|
||||
├── HudOverlay — painel POSIÇÃO + minimapa
|
||||
└── ChatPanel — fluxo SSE /city/chat/{agent}
|
||||
|
||||
Backend (Laravel)
|
||||
├── CityViewerController::data() — stores + agents + city layout
|
||||
├── ChatController — SSE endpoint por agente
|
||||
└── AgentThinkJob (queue) — chama OpenRouter, persiste last_decision</pre>
|
||||
</div>
|
||||
|
||||
<div class="section">
|
||||
<span class="label">2. Componentes</span>
|
||||
<table style="width:100%;border-collapse:collapse;font-size:.9rem">
|
||||
<tr style="border-bottom:1px solid var(--border)"><td style="padding:.5rem"><strong>CameraController</strong></td><td>Pointer-lock, WASD, gravidade simples, raycast contra colisores AABB de prédios</td></tr>
|
||||
<tr style="border-bottom:1px solid var(--border)"><td style="padding:.5rem"><strong>CityGenerator</strong></td><td>Rua central + quadras laterais a partir das posições das lojas; prédios de preenchimento procedural (seed determinística)</td></tr>
|
||||
<tr style="border-bottom:1px solid var(--border)"><td style="padding:.5rem"><strong>StreetMesh</strong></td><td>Asfalto (canvas texture com faixas), calçada de ladrilho, postes a cada N metros</td></tr>
|
||||
<tr style="border-bottom:1px solid var(--border)"><td style="padding:.5rem"><strong>CharacterFactory</strong></td><td>GLTF por <code>agent.type</code>; fallback: cápsula texturizada. Animação Idle/Walk/Run</td></tr>
|
||||
<tr style="border-bottom:1px solid var(--border)"><td style="padding:.5rem"><strong>HudOverlay</strong></td><td>Painel POSIÇÃO (x,y,z, triângulos) + minimapa 2D no canto</td></tr>
|
||||
<tr><td style="padding:.5rem"><strong>ChatPanel</strong></td><td>Abre ao clicar no NPC; mostra nome, status (pensando/respondendo), mensagens; envia via POST e recebe via SSE</td></tr>
|
||||
</table>
|
||||
</div>
|
||||
|
||||
<div class="section">
|
||||
<span class="label">3. Fluxo de dados</span>
|
||||
<ol>
|
||||
<li>Viewport carrega → <code>GET /city/data</code> → lojas + agentes + layout de ruas</li>
|
||||
<li><code>CityGenerator</code> monta ruas e prédios; prédios de loja ganham fachada custom</li>
|
||||
<li>Usuário anda (WASD) → colisão por AABB → câmera segue</li>
|
||||
<li>Clica em NPC → <code>ChatPanel</code> abre → <code>GET /city/chat/{agent}/stream</code> (SSE)</li>
|
||||
<li>Envia mensagem → <code>POST /city/chat/{agent}</code> → job enfileirado → OpenRouter → persiste <code>last_decision</code> → SSE emite resposta</li>
|
||||
<li>HUD recalcula posição a cada frame</li>
|
||||
</ol>
|
||||
</div>
|
||||
|
||||
<div class="section">
|
||||
<span class="label">4. Tratamento de erros</span>
|
||||
<ul>
|
||||
<li>SSE cai → reconexão automática com backoff, indicador "reconectando"</li>
|
||||
<li>OpenRouter falha → <code>error_count++</code>, backoff exponencial, status vira <code>error</code> no painel</li>
|
||||
<li>GLTF ausente → fallback silencioso para cápsula (nunca quebra a cena)</li>
|
||||
<li>Colisão detecta NaN → reposiciona no spawn</li>
|
||||
</ul>
|
||||
</div>
|
||||
|
||||
<div class="section">
|
||||
<span class="label">5. Testes</span>
|
||||
<ul>
|
||||
<li><strong>PHPUnit</strong>: <code>CityViewerController::data()</code> retorna layout; <code>ChatController</code> valida input e rate-limit; job persiste <code>last_decision</code></li>
|
||||
<li><strong>JS</strong>: <code>CameraController</code> (colisão, WASD), <code>CityGenerator</code> (determinístico com seed), reconexão SSE</li>
|
||||
<li><strong>Manual</strong>: navegar, colidir, conversar com NPC, verificar HUD</li>
|
||||
</ul>
|
||||
</div>
|
||||
|
||||
<hr style="border-color:var(--border);margin:1.5rem 0">
|
||||
|
||||
<p style="text-align:center"><strong>Esse design está correto? Aprovo para escrever a especificação formal.</strong></p>
|
||||
<div class="options">
|
||||
<div class="option" data-choice="approve" onclick="toggleSelect(this)">
|
||||
<div class="letter">✅</div>
|
||||
<div class="content"><h3>Aprovar design</h3><p>Escrever spec → revisão → plano de implementação</p></div>
|
||||
</div>
|
||||
<div class="option" data-choice="revise" onclick="toggleSelect(this)">
|
||||
<div class="letter">✏️</div>
|
||||
<div class="content"><h3>Revisar</h3><p>Quero mudar algo antes de seguir</p></div>
|
||||
</div>
|
||||
</div>
|
||||
Binary file not shown.
|
After Width: | Height: | Size: 288 KiB |
Binary file not shown.
|
After Width: | Height: | Size: 309 KiB |
Binary file not shown.
|
After Width: | Height: | Size: 320 KiB |
Binary file not shown.
|
After Width: | Height: | Size: 413 KiB |
@@ -0,0 +1,85 @@
|
||||
<div style="text-align:center;margin-bottom:1.5rem">
|
||||
<h2>✅ Entendi o Visual Alvo</h2>
|
||||
<p class="subtitle">Baseado nas 4 telas de exemplo — a diferença para o que existe hoje é enorme</p>
|
||||
</div>
|
||||
|
||||
<div class="split">
|
||||
<div class="mockup">
|
||||
<div class="mockup-header">Hoje (existe)</div>
|
||||
<div class="mockup-body" style="text-align:center;padding:1.5rem">
|
||||
<div style="background:#14532d;border:1px solid #334155;border-radius:.5rem;height:100px;display:flex;align-items:center;justify-content:center;gap:8px">
|
||||
<div style="width:20px;height:20px;background:#0ea5e9;border-radius:3px"></div>
|
||||
<div style="width:25px;height:30px;background:#8b5cf6;border-radius:3px"></div>
|
||||
<div style="width:15px;height:15px;background:#f59e0b;border-radius:999px"></div>
|
||||
</div>
|
||||
<p style="margin-top:.75rem;font-size:.85rem">Vista isométrica · caixas coloridas · cápsulas amarelas</p>
|
||||
</div>
|
||||
</div>
|
||||
<div class="mockup">
|
||||
<div class="mockup-header">Alvo (imagens de exemplo)</div>
|
||||
<div class="mockup-body" style="text-align:center;padding:1.5rem">
|
||||
<div style="background:linear-gradient(#87ceeb 0%, #87ceeb 35%, #333 36%, #333 100%);border:1px solid #555;border-radius:.5rem;height:100px;position:relative;overflow:hidden">
|
||||
<div style="position:absolute;left:0;top:0;bottom:0;width:35%;background:linear-gradient(#d4a843,#8b6914);border-right:3px solid #222"></div>
|
||||
<div style="position:absolute;right:0;top:0;bottom:0;width:35%;background:linear-gradient(#c49a3a,#7a5a12);border-left:3px solid #222"></div>
|
||||
<div style="position:absolute;left:50%;bottom:0;transform:translateX(-50%);width:10px;height:100%;background:#222"></div>
|
||||
<div style="position:absolute;left:30%;bottom:40%;width:15px;height:15px;background:#555;border-radius:50%"></div>
|
||||
<div style="position:absolute;right:30%;bottom:40%;width:15px;height:15px;background:#555;border-radius:50%"></div>
|
||||
</div>
|
||||
<p style="margin-top:.75rem;font-size:.85rem">1ª pessoa · asfalto + faixas · prédios fachadas · personagens 3D</p>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<hr style="border-color:var(--border);margin:2rem 0">
|
||||
|
||||
<h3 style="text-align:center">Gap — o que precisa ser construído</h3>
|
||||
|
||||
<div class="options" style="margin-top:1rem" data-multiselect>
|
||||
<div class="option" data-choice="fps-camera" onclick="toggleSelect(this)">
|
||||
<div class="letter">1</div>
|
||||
<div class="content">
|
||||
<h3>Câmera 1ª pessoa / 3ª pessoa</h3>
|
||||
<p>Substituir a órbita por WASD + mouse, com colisão contra prédios e pedestres</p>
|
||||
<p style="color:var(--muted);font-size:.85rem;margin-top:.4rem">Bloqueante: sem isso, não tem a experiência das imagens</p>
|
||||
</div>
|
||||
</div>
|
||||
<div class="option" data-choice="street" onclick="toggleSelect(this)">
|
||||
<div class="letter">2</div>
|
||||
<div class="content">
|
||||
<h3>Rua realista</h3>
|
||||
<p>Asfalto escuro, faixas brancas, calçada de ladrilho, postes, semáforos</p>
|
||||
</div>
|
||||
</div>
|
||||
<div class="option" data-choice="buildings" onclick="toggleSelect(this)">
|
||||
<div class="letter">3</div>
|
||||
<div class="content">
|
||||
<h3>Prédios com fachadas</h3>
|
||||
<p>Janelas, portas, estrutura escura, fachadas amarelo/mostarda e marrom — não caixas planas</p>
|
||||
</div>
|
||||
</div>
|
||||
<div class="option" data-choice="characters" onclick="toggleSelect(this)">
|
||||
<div class="letter">4</div>
|
||||
<div class="content">
|
||||
<h3>Personagens 3D estilo anime</h3>
|
||||
<p>Modelos detalhados com cabelo, roupas, animação de andar — substituir cápsulas amarelas</p>
|
||||
<p style="color:var(--muted);font-size:.85rem;margin-top:.4rem">Requer modelo 3D (GLTF) ou compra/asset pack</p>
|
||||
</div>
|
||||
</div>
|
||||
<div class="option" data-choice="hud" onclick="toggleSelect(this)">
|
||||
<div class="letter">5</div>
|
||||
<div class="content">
|
||||
<h3>HUD — Painel POSIÇÃO</h3>
|
||||
<p>Coordenadas x,y,z, no chão, triângulos de colisão no canto inferior esquerdo</p>
|
||||
</div>
|
||||
</div>
|
||||
<div class="option" data-choice="chat" onclick="toggleSelect(this)">
|
||||
<div class="letter">6</div>
|
||||
<div class="content">
|
||||
<h3>Chat com NPCs (OpenRouter)</h3>
|
||||
<p>Painel de diálogo com nome, status (pensando/respondendo), conversa em tempo real</p>
|
||||
<p style="color:var(--muted);font-size:.85rem;margin-top:.4rem">Integração direta com agentes existentes no banco</p>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<p style="margin-top:1.5rem;text-align:center;color:var(--muted)">Marque os itens que confirma estar no escopo da Fase 2 e me diga se algo está faltando ou sobrando.</p>
|
||||
@@ -0,0 +1,29 @@
|
||||
<div style="text-align:center;margin-bottom:1rem">
|
||||
<h2>📷 Imagens de Referência</h2>
|
||||
<p class="subtitle">As quatro telas de exemplo na raiz do projeto — me ajude a entender o que cada uma mostra</p>
|
||||
</div>
|
||||
|
||||
<div class="cards">
|
||||
<div class="card" data-choice="1" onclick="toggleSelect(this)">
|
||||
<h3>Tela 1</h3>
|
||||
<img src="/files/exemplo1.png" style="max-width:100%;border-radius:.6rem;border:1px solid var(--border)">
|
||||
<p style="color:var(--muted);font-size:.85rem">Descreva: o que esta tela mostra?</p>
|
||||
</div>
|
||||
<div class="card" data-choice="2" onclick="toggleSelect(this)">
|
||||
<h3>Tela 2</h3>
|
||||
<img src="/files/exemplo2.png" style="max-width:100%;border-radius:.6rem;border:1px solid var(--border)">
|
||||
<p style="color:var(--muted);font-size:.85rem">Descreva: o que esta tela mostra?</p>
|
||||
</div>
|
||||
<div class="card" data-choice="3" onclick="toggleSelect(this)">
|
||||
<h3>Tela 3</h3>
|
||||
<img src="/files/exemplo3.png" style="max-width:100%;border-radius:.6rem;border:1px solid var(--border)">
|
||||
<p style="color:var(--muted);font-size:.85rem">Descreva: o que esta tela mostra?</p>
|
||||
</div>
|
||||
<div class="card" data-choice="4" onclick="toggleSelect(this)">
|
||||
<h3>Tela 4</h3>
|
||||
<img src="/files/exemplo4.png" style="max-width:100%;border-radius:.6rem;border:1px solid var(--border)">
|
||||
<p style="color:var(--muted);font-size:.85rem">Descreva: o que esta tela mostra?</p>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<p style="margin-top:1.5rem;text-align:center;color:var(--muted);font-weight:600">Por favor, no terminal, me diga o que cada imagem mostra para eu entender o visual que você quer atingir.</p>
|
||||
Reference in New Issue
Block a user