feat(city): add player marketplace, mission journal, character customization and presence
- Player-to-player marketplace with listings, buying and selling - Mission system with progress tracking and money rewards - Character appearance customization (skin, hair, face, beard, accessory) - Multiplayer presence feed showing nearby citizens in near-real-time - Admin world dashboard with live platform metrics - Bus and train transportation with temporary ride state - Mobile joystick controls and minimap HUD - Education bonus applied to work salary
This commit is contained in:
@@ -0,0 +1,81 @@
|
||||
<?php
|
||||
|
||||
namespace App\Http\Controllers\Web\Admin;
|
||||
|
||||
use App\Http\Controllers\Controller;
|
||||
use App\Models\Building;
|
||||
use App\Models\Character;
|
||||
use App\Models\CharacterMessage;
|
||||
use App\Models\City;
|
||||
use App\Models\Job;
|
||||
use App\Models\MarketListing;
|
||||
use App\Models\Mission;
|
||||
use App\Models\Store;
|
||||
use App\Models\Transaction;
|
||||
use App\Models\User;
|
||||
use App\Models\UserConsent;
|
||||
use Illuminate\Http\Request;
|
||||
use Illuminate\Support\Facades\DB;
|
||||
use Illuminate\View\View;
|
||||
|
||||
/**
|
||||
* Administrator world dashboard and metrics.
|
||||
*
|
||||
* Aggregates live city health: citizens, economy, constructions, missions
|
||||
* and marketplace activity so operators can steer the persistent world.
|
||||
*/
|
||||
class AdminWorldController extends Controller
|
||||
{
|
||||
/**
|
||||
* HTML dashboard for the admin area.
|
||||
*/
|
||||
public function index(Request $request): View
|
||||
{
|
||||
abort_unless($request->user()?->isAdmin(), 403);
|
||||
|
||||
return view('admin.world.index', [
|
||||
'metrics' => $this->metrics(),
|
||||
]);
|
||||
}
|
||||
|
||||
/**
|
||||
* JSON metrics (also used by the report command).
|
||||
*/
|
||||
public function metrics(): array
|
||||
{
|
||||
return [
|
||||
'users' => [
|
||||
'total' => User::query()->count(),
|
||||
'pending' => User::query()->where('status', User::STATUS_PENDING)->count(),
|
||||
'active' => User::query()->where('status', User::STATUS_ACTIVE)->count(),
|
||||
'banned' => User::query()->where('status', User::STATUS_BANNED)->count(),
|
||||
'consents' => UserConsent::query()->count(),
|
||||
],
|
||||
'cities' => City::query()->count(),
|
||||
'characters' => [
|
||||
'total' => Character::query()->count(),
|
||||
'online' => Character::query()->where('is_online', true)->count(),
|
||||
'hospitalized' => Character::query()->where('state', Character::STATE_HOSPITAL)->count(),
|
||||
'avg_health' => (int) round(Character::query()->avg('health') ?? 0),
|
||||
'avg_education' => (int) round(Character::query()->avg('education') ?? 0),
|
||||
'total_money' => round((float) Character::query()->sum('money'), 2),
|
||||
],
|
||||
'world' => [
|
||||
'stores' => Store::query()->count(),
|
||||
'buildings' => Building::query()->count(),
|
||||
'houses_complete' => Building::query()->where('type', 'house')->where('is_complete', true)->count(),
|
||||
'jobs' => Job::query()->count(),
|
||||
'messages' => CharacterMessage::query()->count(),
|
||||
'transactions' => Transaction::query()->count(),
|
||||
'transaction_volume' => round((float) Transaction::query()->sum('amount'), 2),
|
||||
],
|
||||
'market' => [
|
||||
'listings' => MarketListing::query()->where('is_active', true)->count(),
|
||||
],
|
||||
'missions' => [
|
||||
'active' => Mission::query()->where('is_active', true)->count(),
|
||||
'completed' => DB::table('character_missions')->where('is_completed', true)->count(),
|
||||
],
|
||||
];
|
||||
}
|
||||
}
|
||||
Reference in New Issue
Block a user