Tighten directional light shadow frustum to follow the player and batch static geometries into merged meshes, reducing draw calls significantly. Expand city world bounds to support 72 blocks and add per-frame performance monitoring instrumentation. BREAKING CHANGE: city bounds changed from ±80 to ±120/±160, update any hardcoded client-side world assumptions.
80 lines
2.7 KiB
PHP
Executable File
80 lines
2.7 KiB
PHP
Executable File
<?php
|
||
|
||
namespace Tests\Feature;
|
||
|
||
use App\Models\Character;
|
||
use App\Models\City;
|
||
use App\Models\User;
|
||
use Database\Seeders\CityWorldSeeder;
|
||
use Illuminate\Foundation\Testing\RefreshDatabase;
|
||
use Tests\TestCase;
|
||
|
||
/**
|
||
* World schema and seeding coverage.
|
||
*/
|
||
class CityWorldSeedingTest extends TestCase
|
||
{
|
||
use RefreshDatabase;
|
||
|
||
/**
|
||
* Seeder creates City10, jobs and a character for active users.
|
||
*/
|
||
public function test_seeder_bootstraps_city_jobs_and_characters(): void
|
||
{
|
||
$this->seed(CityWorldSeeder::class);
|
||
|
||
$city = City::query()->where('slug', 'city10')->first();
|
||
$this->assertNotNull($city);
|
||
$this->assertTrue($city->is_active);
|
||
$this->assertSame(4, $city->jobs()->count());
|
||
|
||
$user = User::factory()->create(['status' => User::STATUS_ACTIVE, 'is_active' => true]);
|
||
$this->seed(CityWorldSeeder::class);
|
||
|
||
$this->assertNotNull(Character::query()->where('user_id', $user->id)->first());
|
||
}
|
||
|
||
/**
|
||
* Migration backfills legacy is_active flags onto status.
|
||
*/
|
||
public function test_status_backfill_matches_is_active(): void
|
||
{
|
||
$this->seed(CityWorldSeeder::class);
|
||
|
||
$active = User::where('is_active', true)->where('status', '!=', User::STATUS_ACTIVE)->count();
|
||
$this->assertSame(0, $active);
|
||
}
|
||
|
||
/**
|
||
* The performance-tuned city delivers exactly 72 blocks (9 × 8) with
|
||
* the matching road grid and bounds in the world payload.
|
||
*/
|
||
public function test_layout_has_72_blocks_after_performance_resize(): void
|
||
{
|
||
$this->seed(CityWorldSeeder::class);
|
||
|
||
$user = User::factory()->create(['status' => User::STATUS_ACTIVE, 'is_active' => true]);
|
||
Character::ensureForUser($user);
|
||
$this->actingAs($user);
|
||
|
||
$payload = $this->getJson('/city/data')->assertOk()->json();
|
||
|
||
$this->assertCount(72, $payload['layout']['blocks']);
|
||
|
||
$zRoads = count(array_filter($payload['layout']['roads'], fn (array $r): bool => $r['axis'] === 'z'));
|
||
$xRoads = count(array_filter($payload['layout']['roads'], fn (array $r): bool => $r['axis'] === 'x'));
|
||
// Server payload: 10 vertical + 9 horizontal grid roads (the bridge
|
||
// and north extension are appended client-side at build time).
|
||
$this->assertSame(10, $zRoads);
|
||
$this->assertSame(9, $xRoads);
|
||
|
||
$this->assertEquals(-120, $payload['city']['bounds']['min_x']);
|
||
$this->assertEquals(160, $payload['city']['bounds']['max_x']);
|
||
$this->assertEquals(-120, $payload['city']['bounds']['min_z']);
|
||
$this->assertEquals(120, $payload['city']['bounds']['max_z']);
|
||
|
||
// The sparse plaza pattern (~1 in 4 cells) scales with the city.
|
||
$this->assertGreaterThanOrEqual(10, count($payload['plazas']));
|
||
}
|
||
}
|