feat(city): add airports, ATC agent, luminous signs, and AI model fallback chain
- Add two airports (north/south) with full geometry: runways, taxiways,
aprons, terminals, hangars, stands, and helipads; walkable airport
grounds extend beyond city bounds.
- Introduce ATC AI agent ("Torre de Controle City10") using AI_ATC_MODEL
to generate takeoff clearances; includes dispatch endpoint with
30-second cooldown and deterministic fallback on failure.
- Implement AI model fallback chain: preferred model → AI_FALLBACK_MODEL
before failing, applied in ChatController and PersonTalkController.
- Add luminous sign labels (letreiros) for plazas, beach, food, hospital,
school, city hall, and airports with day/night glow.
- Fix city presence cache: compute is_me per viewer instead of baking
into shared per-second cache to prevent cross-user flag leakage.
- Add tests: AirportTest, CityPresenceTest, SignLabelsTest, and
PersonTalkTest fallback model retry scenario.
This commit is contained in:
@@ -2,6 +2,7 @@
|
||||
|
||||
namespace Database\Seeders;
|
||||
|
||||
use App\Models\AiAgent;
|
||||
use App\Models\Building;
|
||||
use App\Models\Character;
|
||||
use App\Models\City;
|
||||
@@ -9,6 +10,7 @@ use App\Models\Job;
|
||||
use App\Models\Mission;
|
||||
use App\Models\Store;
|
||||
use App\Models\User;
|
||||
use App\Support\Airports;
|
||||
use Illuminate\Database\Seeder;
|
||||
|
||||
/**
|
||||
@@ -40,6 +42,31 @@ class CityWorldSeeder extends Seeder
|
||||
],
|
||||
);
|
||||
|
||||
// --- Control tower agent (airport clearances) ---------------------
|
||||
// Positioned at the north airport tower; model comes from
|
||||
// AI_ATC_MODEL (poolside/laguna-xs-2.1:free by default) and is
|
||||
// re-validated against the allow-list before use.
|
||||
$tower = Airports::geometry($city)['sites'][0]['tower']['center'];
|
||||
$atcModel = (string) config('ai.atc_model');
|
||||
if (! in_array($atcModel, config('ai.allowed_models', []), true)) {
|
||||
$atcModel = 'poolside/laguna-xs-2.1:free';
|
||||
}
|
||||
AiAgent::updateOrCreate(
|
||||
['name' => 'Torre de Controle City10'],
|
||||
[
|
||||
'type' => 'atc',
|
||||
'model' => $atcModel,
|
||||
'system_prompt' => 'Você é a torre de controle aéreo do Aeroporto City10 Norte. '
|
||||
.'Autorize decolagens e pousos com linguagem formal, curta e clássica de controle '
|
||||
.'de tráfego aéreo, sempre em português, citando o voo, a companhia e a pista.',
|
||||
'current_goal' => 'Gerenciar decolagens, pousos e o tráfego dos dois aeroportos com segurança',
|
||||
'status' => 'active',
|
||||
'pos_x' => (float) $tower[0],
|
||||
'pos_y' => 0,
|
||||
'pos_z' => (float) $tower[1],
|
||||
],
|
||||
);
|
||||
|
||||
$bakery = Store::where('type', 'bakery')->orderBy('id')->first();
|
||||
$market = Store::where('type', 'market')->orderBy('id')->first();
|
||||
|
||||
|
||||
Reference in New Issue
Block a user