* @license MIT * * Register this provider by adding ONE line to app/Providers/AppServiceProvider.php: * $this->app->register(\Pterodactyl\Addons\AdvancedAdmin\AddonServiceProvider::class); * * See patches/PATCHES.md for full patch instructions. */ namespace Pterodactyl\Addons\AdvancedAdmin; use Illuminate\Support\ServiceProvider; use Illuminate\Console\Scheduling\Schedule; class AddonServiceProvider extends ServiceProvider { /** * Register addon bindings. */ public function register(): void { // Merge addon config (won't overwrite user's published config) $this->mergeConfigFrom( __DIR__ . '/../../../config/advanced-admin.php', 'advanced-admin' ); // Bind the PermissionResolver as a singleton for performance $resolver = 'Pterodactyl\Addons\AdvancedAdmin\Services\Roles\PermissionResolver'; if (class_exists($resolver)) { $this->app->singleton($resolver); } } /** * Bootstrap addon services. */ public function boot(): void { // ── Routes ──────────────────────────────────────────────────────────── $clientRoutes = __DIR__ . '/../../../routes/addon-client.php'; $appRoutes = __DIR__ . '/../../../routes/addon-application.php'; if (file_exists($clientRoutes)) { $this->loadRoutesFrom($clientRoutes); } if (file_exists($appRoutes)) { $this->loadRoutesFrom($appRoutes); } // ── Migrations ──────────────────────────────────────────────────────── $migrationsPath = __DIR__ . '/../../../database/migrations/addon'; if (is_dir($migrationsPath)) { $this->loadMigrationsFrom($migrationsPath); } // ── Scheduled Jobs ──────────────────────────────────────────────────── $this->callAfterResolving(Schedule::class, function (Schedule $schedule) { // Network metric collection $collectJob = 'Pterodactyl\Addons\AdvancedAdmin\Jobs\Network\CollectNetworkMetricsJob'; $downsampleJob = 'Pterodactyl\Addons\AdvancedAdmin\Jobs\Network\DownsampleNetworkMetricsJob'; $pruneNetJob = 'Pterodactyl\Addons\AdvancedAdmin\Jobs\Network\PruneNetworkMetricsJob'; $pruneRevJob = 'Pterodactyl\Addons\AdvancedAdmin\Jobs\Revisions\PruneFileRevisionsJob'; $expireJob = 'Pterodactyl\Addons\AdvancedAdmin\Jobs\Console\ExpireStalePlayersJob'; if (config('advanced-admin.network.enabled') && class_exists($collectJob)) { $schedule->job(new $collectJob()) ->everyTenSeconds() ->withoutOverlapping(5) ->onOneServer(); if (class_exists($downsampleJob)) { $schedule->job(new $downsampleJob()) ->hourly() ->withoutOverlapping(30) ->onOneServer(); } if (class_exists($pruneNetJob)) { $schedule->job(new $pruneNetJob()) ->daily() ->withoutOverlapping(60) ->onOneServer(); } } if (config('advanced-admin.revisions.enabled') && class_exists($pruneRevJob)) { $schedule->job(new $pruneRevJob()) ->daily() ->withoutOverlapping(60) ->onOneServer(); } if (config('advanced-admin.console.enabled') && class_exists($expireJob)) { $schedule->job(new $expireJob()) ->everyFiveMinutes() ->withoutOverlapping(4); } }); // ── Event Listeners ─────────────────────────────────────────────────── // Console output listener (parses join/leave for player cache) $consoleEvent = 'Pterodactyl\Events\Server\ConsoleDataReceived'; $consoleListener = 'Pterodactyl\Addons\AdvancedAdmin\Listeners\Console\ConsoleOutputListener'; if (class_exists($consoleEvent) && class_exists($consoleListener)) { $this->app['events']->listen($consoleEvent, $consoleListener); } // ── Artisan Commands ────────────────────────────────────────────────── if ($this->app->runningInConsole()) { $commands = []; $candidates = [ 'Pterodactyl\Addons\AdvancedAdmin\Console\Commands\CollectNetworkCommand', ]; foreach ($candidates as $cmd) { if (class_exists($cmd)) { $commands[] = $cmd; } } if (!empty($commands)) { $this->commands($commands); } } // ── Publishable Assets ──────────────────────────────────────────────── $this->publishes([ __DIR__ . '/../../../config/advanced-admin.php' => config_path('advanced-admin.php'), ], 'advanced-admin-config'); $this->publishes([ __DIR__ . '/../../../config/addon-commands' => base_path('config/addon-commands'), ], 'advanced-admin-commands'); } }