Initial commit of the complete City10 virtual city simulation platform. Backend (Laravel 13): - REST API with Sanctum tokens and session-based web authentication - Role-based access control (admin/user) with middleware protection - AI agent CRUD with OpenRouter.ai integration restricted to free models - Store management with 3D coordinates and AI shopkeeper assignment - Versioned legal documents (Terms, Privacy, Cookies) with LGPD audit trail - Math CAPTCHA on public forms and multi-language support (pt_BR, en, es) Frontend: - Responsive Blade templates with Tailwind CSS v4 - Three.js 3D city viewer with SSE chat streaming to AI agents - Admin panel for store and user administration Infrastructure: - MariaDB/MySQL database with comprehensive migrations - Database seeders for demo content and test accounts - PHPUnit test suite and Laravel Pint code styling - Vite build configuration with hot reload
53 lines
1.8 KiB
PHP
Executable File
53 lines
1.8 KiB
PHP
Executable File
<?php
|
|
|
|
namespace App\Http\Controllers\Api;
|
|
|
|
use App\Http\Controllers\Controller;
|
|
use App\Models\AiAgent;
|
|
use App\Models\Store;
|
|
use Illuminate\Http\JsonResponse;
|
|
|
|
/**
|
|
* Aggregated city snapshot consumed by the Three.js frontend.
|
|
*
|
|
* Provides a single lightweight payload describing the static and dynamic
|
|
* elements of the virtual city (stores and AI agents with coordinates).
|
|
*/
|
|
class CityController extends Controller
|
|
{
|
|
/**
|
|
* Return the current world state used to bootstrap the 3D scene.
|
|
*/
|
|
public function world(): JsonResponse
|
|
{
|
|
$stores = Store::query()
|
|
->get(['id', 'name', 'type', 'pos_x', 'pos_y', 'pos_z', 'width', 'height', 'depth', 'is_open'])
|
|
->map(fn (Store $store): array => [
|
|
'id' => $store->id,
|
|
'name' => $store->name,
|
|
'type' => $store->type,
|
|
'position' => [(float) $store->pos_x, (float) $store->pos_y, (float) $store->pos_z],
|
|
'size' => [(float) $store->width, (float) $store->height, (float) $store->depth],
|
|
'is_open' => $store->is_open,
|
|
]);
|
|
|
|
$agents = AiAgent::query()
|
|
->where('status', '!=', 'paused')
|
|
->get(['id', 'name', 'type', 'status', 'pos_x', 'pos_y', 'pos_z', 'rotation_y'])
|
|
->map(fn (AiAgent $agent): array => [
|
|
'id' => $agent->id,
|
|
'name' => $agent->name,
|
|
'type' => $agent->type,
|
|
'status' => $agent->status,
|
|
'position' => [(float) $agent->pos_x, (float) $agent->pos_y, (float) $agent->pos_z],
|
|
'rotation_y' => (float) $agent->rotation_y,
|
|
]);
|
|
|
|
return response()->json([
|
|
'generated_at' => now()->toIso8601String(),
|
|
'stores' => $stores,
|
|
'agents' => $agents,
|
|
]);
|
|
}
|
|
}
|