feat(port): add sea port with quay, terminal, berths, and AI port master

Adds a new port district on the north-east coast with walkable quay, container yard, terminal, gantry cranes, and berths. Includes AI-driven port master (Capitão do Porto) and dock workers for ship dispatch, plus full frontend rendering of ships, boats, and trucks.
This commit is contained in:
2026-10-31 23:33:06 -03:00
parent e230c391ad
commit 580c830ffb
13 changed files with 1338 additions and 42 deletions
+39
View File
@@ -98,6 +98,45 @@ class CityWorldSeeder extends Seeder
);
}
// --- Port staff: the Capitania (AI clearances) + dock workers ----
$portModel = (string) config('ai.default_model');
if (! in_array($portModel, config('ai.allowed_models', []), true)) {
$portModel = 'deepseek/deepseek-v4-flash-0731';
}
AiAgent::updateOrCreate(
['name' => 'Capitão do Porto'],
[
'type' => 'port_master',
'model' => $portModel,
'system_prompt' => 'Você é o Capitão do Porto da cidade virtual City10. Autorize '
.'atracações, partidas e manobras de navios com linguagem marítima formal e curta, '
.'sempre em português, citando o navio, a companhia e o berço. Nunca forneça '
.'e-mail, senha ou dados de conta de ninguém.',
'current_goal' => 'Coordenar as movimentações dos navios nos berços com segurança',
'status' => 'active',
'pos_x' => 256,
'pos_y' => 0,
'pos_z' => -298,
],
);
foreach ([['Estivador 01', 264, -340], ['Estivador 02', 240, -360]] as [$name, $px, $pz]) {
AiAgent::updateOrCreate(
['name' => $name],
[
'type' => 'dock_worker',
'model' => $portModel,
'system_prompt' => 'Você é '.$name.', estivador do Porto City10 que trabalha no cais '
.'movimentando containers. Fale de forma direta e trabalhadora, em português, '
.'sem inventar dados pessoais de usuários.',
'current_goal' => 'Apoiar a movimentação de containers no pátio e no cais',
'status' => 'active',
'pos_x' => $px,
'pos_y' => 0,
'pos_z' => $pz,
],
);
}
$bakery = Store::where('type', 'bakery')->orderBy('id')->first();
$market = Store::where('type', 'market')->orderBy('id')->first();