Implement proper ground clearance and landing gear for all aircraft types (airliner, regional, prop). Add cockpit glass at the nose, winglets at wing tips, and configurable propeller blade length. Wheels now touch the runway surface (y=0) with the fuselage lifted by clearance values.
City10 — Cidade 3D Virtual com Agentes de IA
City10 é uma plataforma full-stack de simulação urbana 3D com agentes de inteligência artificial, construída sobre Laravel 13 e Three.js. O visualizador3D é jogável no navegador: trânsito semafórico, pedestres, agentes (Prefeito, lojistas), conversas de rua com IA, praças com academia e uma praia com lazer. O raciocínio dos NPCs acontece através da API OpenRouter.ai, restrito a uma lista de modelos gratuitos.
Plataforma operada pela Syspanel — Santa Rita do Sapucaí/MG, Brasil. Contato: contato@syspanel.com.br · WhatsApp: (35) 99226-1684 · www.syspanel.com.br
Visão Geral da Arquitetura
| Camada | Tecnologia | Responsabilidade |
|---|---|---|
| Backend / Painel Admin | Laravel 13 (PHP ≥ 8.3) | Autenticação, API REST, regras de negócio, consentimento LGPD |
| Banco de Dados | MariaDB (MySQL) | Persistência de usuários, lojas, agentes, conversas e consentimentos |
| Cache / Fila | Database (sessões/cache/jobs) | Sessões, cache, agendamentos e throttle |
| Frontend 3D | Three.js | Mundo jogável no navegador (cidade, trânsito, praia, clima) |
| Tempo Real | Polling HTTP + SSE | Presence (~2,5 s), chat (~2,5 s) e stream de resposta de NPC (SSE) |
| Cérebro dos Agentes | OpenRouter.ai | Raciocínio dos NPCs e conversas com modelos gratuitos |
Fase 1 — Plataforma (Entregue)
- Estrutura Laravel 13 com autenticação diferenciada (Admin / Usuário Comum).
- Migrations: usuários com
role, lojas com coordenadas 3D (pos_x,pos_y,pos_z), agentes de IA e trilha de consentimento legal (LGPD). - API REST (Sanctum) para usuários, lojas, agentes, cidade e documentos legais.
- CAPTCHA matemático próprio (soma), sem dependências externas, nos formulários públicos.
- Multi-idioma: Português (Brasil), Inglês e Espanhol — selecionável pelo usuário.
- Termos de Uso, Política de Privacidade e Política de Cookies (LGPD), versionados e com aceite auditável (data, hora, versão, IP).
- Banner de cookies com link para os Termos de Uso e Privacidade.
- Página inicial responsiva (desktop e smartphone).
Fase 2 — Mundo 3D Jogável (Entregue)
O visualizador /city carrega o mundo completo em tempo real:
- Cidade de 72 quarteirões (grade 9 × 8 de blocos de 40 m; bounds
−120..160 × −120..120), com rio e ponte a oeste, extensão rodoviária ao sul, casas de jogadores e um conjunto de lugares públicos com letreiros luminosos: hospital, escola, prefeitura, universidade, corpo de bombeiros (prédios cívicos) e supermercado, drogaria, restaurante, cabeleireiro, banco, hotel e shopping (11 lojas no total, todas com placa frontal + letreiro vertical blade). - Trânsito: carros, motos, bikes e ônibus com tráfego à direita, loop por quarteirão e semáforos por cruzamento (fases NS/EW com amarelos e all-red; veículos param na linha de parada antes das faixas).
- Faixas zebradas reais (barras longitudinais paralelas ao fluxo, design MUTCD) com calçadas e meio-fios interrompidos nas travessias — 323 faixas no layout atual.
- Pedestres com travessia sincronizada ao semáforo; bloqueio de travessia do jogador no vermelho.
- Praças (1 a cada 4 células) com academia externa: exercícios com pose, efeito em saúde/energia e missão “Shape em dia”.
- Praia a leste (
/city+App\Support\Beach): areia, mar com ondas animadas (deslocamento de vértices), espuma na orla, banhistas, nadadores, surfistas, salva-vidas (torre + patrulha), quadra de basquete com jogadores e bola em arremesso, barracas de comidas, cadeiras e guarda-sóis. O jogador pode relaxar na areia (teclaE→POST /city/actions/beach), recuperando energia/saúde por tick até o máximo. - Dois aeroportos derivados dos bounds (pavimento + sinalização de
pista com designadores, taxiways com eixo amarelo, pátio de embarque com
posições de estacionamento de aeronaves, terminal com pontes articuladas,
hangars, torre de controle e helipista): 7 aeronaves de 7 companhias
(jato comercial, jato regional, monomotor e helicóptero) executam o ciclo
completo taxi → decolagem → cruíse sobre a cidade → aproximação → pouso
→ taxi → gate, com contagem de decolagens/pousos em
stats().flights. - Torre de controle com IA: o agente
atc"Torre de Controle City10" (modeloAI_ATC_MODEL,poolside/laguna-xs-2.1:free) gera clearances de decolagem a cada decolagem (POST /city/airport/dispatch, cooldown de 30 s) numa cadeia de modelosAI_ATC_MODEL→ default →AI_FALLBACK_MODEL(xiaomi/mimo-v2.6-flash), com texto determinístico quando tudo falha; o clearance mais recente aparece como aviso "✈ ...". - Agentes vivos: prefeito itinerante, lojistas nas lojas, pedestres com rotas, mais trens (passagem de nível com barreiras), ônibus/trem embarcáveis, avião e barcos no rio.
- Dia/noite e clima com ciclo de horas, névoa, chuva e sombras que seguem o jogador.
- Conversas de rua com outros jogadores e NPCs (ver próxima seção).
- Performance: batching estático por material, sombra seguindo o jogador (janela ±120), lâmpadas/rodas com LOD por distância e fachadas a 256 px — medições ~30–60 fps numa GTX 770.
Controles
| Controle | Ação |
|---|---|
W A S D |
Andar (A/D = lateral) |
| Mouse (pointer lock) | Olhar; arrastar na cena quando sem lock |
← → |
Viram a câmera (não andam de lado) |
| Joystick virtual (mobile) | Vertical = andar, horizontal = virar a câmera |
E |
Contexto: exercício na praça / relaxar na praia / parar |
Espaço |
Pular |
| Clique num NPC | Abrir chat |
| Chegar perto de alguém | Chat abre sozinho; sai de perto ele fecha |
Conversas de Rua (/talk/person) e IA por Personagem
- Registro por dia: cada fala gravada em
person_talks(from/tode character ou agent +talked_on+is_fallback), consultável viaGET /talk/person?kind=agent|character&peer=ID. - Fio da meada: o histórico completo (dias anteriores + hoje) é enviado
como contexto nas respostas de IA — placeholders de erro (
is_fallback) ficam visíveis na UI mas nunca entram no contexto do modelo. - Quem responde:
- Par com humano vivo (sessão tocada nos últimos 5 min) → relay puro, nunca é substituído por IA;
- Par sem humano (cidadãos demo, NPCs) → persona anônima de morador responde via OpenRouter, sem dados cadastrais no payload.
- Resposta de IA é gerada after-response (não depende de worker de
fila), com espaçamento por par, allow-list de modelos, fallback localizado
em falha e auditoria em
last_decision. - Identidade por personagem: colunas em
characters—ai_model,ai_age,ai_gender,ai_personality,ai_bio(persona injetada no prompt; recém-criados já nascem com personalidade/idade). - Modelo por personagem (ordem de resolução, sempre validado em
allowed_models): colunaai_model→ mapaAI_CHARACTER_MODELS(id ou nome) → slot determinístico do poolAI_MODELS→AI_DEFAULT_MODEL.
Requisitos
- PHP ≥ 8.3 (com
pdo_mysql,mbstring,curl,zip,gd,bcmath) - Composer 2
- MariaDB ≥ 10.6 (ou MySQL ≥ 8.0)
- Node.js ≥ 18 (apenas para assets Vite/Tailwind, opcional na Fase 1)
- Docker (opcional, para o ambiente
dockercity10)
Instalação
1. Dependências PHP
composer install
2. Configuração do ambiente
cp .env.example .env
php artisan key:generate
Edite o .env e configure o banco de dados:
DB_CONNECTION=mariadb
DB_HOST=127.0.0.1
DB_PORT=3306
DB_DATABASE=laravel
DB_USERNAME=root
DB_PASSWORD=<sua_senha>
3. Chave do OpenRouter.ai e modelos
A chave não é versionada. Insira-a apenas no .env local:
OPENROUTER_API_KEY=<sua_chave>
AI_DEFAULT_MODEL=deepseek/deepseek-v4-flash-0731
# Pool de modelos gratuitos distribuídos deterministicamente entre os
# personagens (cada um mantém o próprio modelo estável).
AI_MODELS=deepseek/deepseek-v4-flash-0731,nvidia/nemotron-3.5-lightning:free,liquid/lfm-2.5-2.6b:free,openrouter/free,nvidia/nemotron-3-ultra-550b-a55b:free
# Override por personagem: "nome ou id=modelo" separado por vírgula.
AI_CHARACTER_MODELS=
# AI_ATC_MODEL: default model of the control-tower agent (airport
# clearances: takeoff authorizations). Must be allow-listed.
AI_ATC_MODEL=poolside/laguna-xs-2.1:free
# AI_FALLBACK_MODEL: tried when the preferred model of a call fails
# (owner-approved paid model with near-zero cost).
AI_FALLBACK_MODEL=xiaomi/mimo-v2.6-flash
4. Banco de dados
php artisan migrate --seed
5. Servidor de desenvolvimento
php artisan serve --port=16980
A aplicação ficará disponível em http://localhost:16980.
Ambiente Docker (dockercity10)
O container dockercity10 já expõe a aplicação na porta do host 16980
(container :80, Apache + PHP-FPM) e o MariaDB na porta 16981. Após clonar
o projeto em /app (bind-mount), rode as migrations dentro do container:
docker exec -it dockercity10 bash -c "cd /app && php artisan migrate --seed"
Contas de Teste (ambiente de desenvolvimento)
| Papel | Senha | |
|---|---|---|
| Administrador | marcocosta@gmx.com |
Mega886ax |
| Usuário Comum | user@sistema.net |
User123 |
⚠️ Estas credenciais são exclusivas para desenvolvimento. Altere-as ou remova-as (
php artisan db:seed --class=UserSeederapós ajustar) antes de qualquer implantação em produção.
Testes
php artisan test # suíte completa (PHPUnit)
./vendor/bin/pint # formatação de código
Destaques da suíte (testes de recurso): autenticação/LGPD, ações da cidade
(exercício, posição com clamp até a orla da praia), social, mercado,
missões, conversas de rua (PersonTalkTest — histórico multidiário,
resolução de modelo, ausência de PII no payload) e lazer na praia
(BeachLeisureTest — geometria no payload, efeitos e zona).
Estrutura de Endpoints da API
Base URL: http://localhost:16980/api (Bearer Sanctum)
Públicos
| Método | Rota | Descrição |
|---|---|---|
| GET | /auth/captcha |
Gera desafio matemático (necessário para login/registro) |
| POST | /auth/login |
Autentica e emite token Sanctum |
| POST | /auth/register |
Cria conta de usuário comum |
| GET | /legal/documents |
Lista a versão atual dos documentos legais |
Autenticados (Bearer token)
| Método | Rota | Descrição |
|---|---|---|
| GET | /auth/me |
Perfil + status de consentimento |
| PATCH | /auth/profile |
Atualiza nome, idioma ou senha |
| POST | /auth/logout |
Revoga o token atual |
| GET | /city/world |
Snapshot da cidade (lojas + agentes com coordenadas 3D) |
| GET/POST | /stores |
Lista/cria lojas |
| GET/PUT/DELETE | /stores/{id} |
Gerencia uma loja (dono ou admin) |
| GET | /stores-world/seed |
Mundo de lojas (seed 3D) |
| GET | /legal/status |
Status de aceite dos documentos |
| POST | /legal/accept |
Registra o aceite (auditoria LGPD) |
| GET | /legal/history |
Histórico de consentimentos do usuário |
Somente Administrador
| Método | Rota | Descrição |
|---|---|---|
| CRUD | /api/users |
Gestão de usuários |
| CRUD | /api/agents |
Gestão de agentes de IA |
| GET | /api/agents-meta/models |
Lista os modelos gratuitos permitidos |
| GET | /api/agents-world/seed |
Mundo de agentes (seed 3D) |
| GET/POST | /stores, /citizens, /cities, /world |
Admin web (aprovação de cidadãos, cidades, mundo) |
Rotas Web da Cidade (sessão de navegador)
Todas exigem login + termos aceitos.
| Método | Rota | Descrição |
|---|---|---|
| GET | /city |
Visualizador 3D (HTML + bundle Three.js) |
| GET | /city/data |
Payload do mundo: layout, lojas, agentes, praças, prédios, beach |
| GET | /city/presence |
Cidadãos online (posições, is_me) — throttle 60/min |
| GET/POST | /talk/person |
Conversas de rua: histórico/contexto e envio (throttle 120 e 30/min) |
| POST | /city/actions/position |
Sincroniza posição (clamp até a orla da praia) |
| POST | /city/actions/{action} |
Ações: eat, drink, sleep, wake, work, study, buy, sell, build, apply-job, exercise, stop-exercise, beach, ride, accident… |
| POST/GET | /city/chat/{agent} (+/stream) |
Conversa com NPC (envio + SSE de resposta) |
| POST/GET | /city/messages/{character} |
Mensagens assíncronas entre personagens |
| POST | /city/social/{verb} · GET /city/social/inbox |
Amizade, casamento, filho, inbox |
| GET | /city/airport |
Sites dos aeroportos, torre (ATC) e clearance atual |
| POST | /city/airport/dispatch |
Pede um clearance de decolagem à torre (cooldown 30 s) |
| GET/POST | /city/market (/buy, /sell) |
Mercado |
| GET/PUT | /city/customize |
Personalização do personagem |
Modelos de IA Permitidos
Somente os modelos abaixo podem ser usados (validado no backend em
config/ai.php; os quatro últimos foram verificados ao vivo no catálogo do
OpenRouter). Exceção aprovada pelo responsável: xiaomi/mimo-v2.6-flash
(pago, custo mínimo ~1,4e-7/token, verificado ao vivo) — usado como
fallback de todas as cadeias de chamada:
poolside/laguna-m.1:free cohere/north-mini-code:free
deepseek/deepseek-v4-flash-0731:free qwen/qwen3.8-27b:free
nvidia/nemotron-3-ultra-550b-a55b:free nvidia/nemotron-3-super-120b-a12b:free
google/gemma-4-31b-it:free google/gemma-4-26b-a4b-it:free
openai/gpt-oss-20b:free nvidia/nemotron-nano-12b-v2-vl:free
nvidia/nemotron-3-nano-omni-30b-a3b-reasoning:free
nvidia/nemotron-3-nano-30b-a3b:free nvidia/nemotron-nano-9b-v2:free
poolside/laguna-xs-2.1:free inclusionai/ling-3.0-flash-vl:free
qwen/qwen3.7-flash:free
deepseek/deepseek-v4-flash-0731 nvidia/nemotron-3.5-lightning:free
liquid/lfm-2.5-2.6b:free openrouter/free
xiaomi/mimo-v2.6-flash (fallback — ver nota acima)
Segurança e Conformidade (LGPD)
- Senhas armazenadas com bcrypt (cast
hashed). - Tokens de API (Sanctum) revogáveis por usuário.
- RBAC: papéis
admin/usercom middleware dedicado. - CAPTCHA matemático nos formulários públicos (login/registro).
- Consentimento auditável: data, hora, versão do documento, IP e user-agent
gravados em
user_consents(imutáveis). - Banner de cookies com opção de aceitar/recusar cookies não essenciais.
- Direitos do titular (art. 18 LGPD): histórico de consentimentos disponível
ao usuário; contato para exercer direitos:
contato@syspanel.com.br. - IA sem PII: ao chamar o OpenRouter envia-se apenas contexto simulado da
cidade e o diálogo/identidade in-world — nunca e-mail, senha ou dados de
conta (regras em
RULES.md, seção 2).
Licença
Software Proprietário — © 2026 Syspanel. Todos os direitos reservados.
Veja o arquivo LICENSE para os termos completos de uso.
Bibliotecas de terceiros utilizadas são compatíveis com uso comercial
(por exemplo: Laravel — MIT; Three.js — MIT). O crédito aos autores originais
está registrado em RULES.md.
Contato
- E-mail: contato@syspanel.com.br
- WhatsApp: (35) 99226-1684
- Site: www.syspanel.com.br
- Localização: Santa Rita do Sapucaí — Minas Gerais — Brasil
© 2026 — Todos os direitos reservados — Powered by Syspanel — www.syspanel.com.br