# MODPACK VERSION CHECKER - IMPLEMENTATION PLAN **Complete code implementation organized by component** All code blocks provided by Gemini Pro research session (February 22, 2026) --- ## 📋 TABLE OF CONTENTS 1. Blueprint Configuration 2. Database Installation Scripts 3. Backend Services (PHP/Laravel) 4. Frontend Components (React/TypeScript) 5. API Provider Implementations 6. Caching & Detection Services 7. Configuration Files --- ## 1. BLUEPRINT CONFIGURATION ### blueprint.yml **Location:** `/blueprint.yml` ```yaml info: name: "Modpack Version Monitor" identifier: "modpackmonitor" description: "Automated version tracking for CurseForge, FTB, and Modrinth." version: "1.0.0" target: "alpha" # UI Injection Configuration injections: - target: resources/scripts/components/server/ServerDetailsBlock.tsx find:

replace: |

``` **Purpose:** Defines extension metadata and UI injection points for Blueprint framework --- ## 2. DATABASE INSTALLATION SCRIPTS ### install.sh - Database Injection Script **Location:** `/scripts/install.sh` **Block 1: Initial Setup & Environment Parsing** ```bash #!/bin/bash # Blueprint Extension Install Script: Modpack Checker PTERO_DIR="/var/www/pterodactyl" if [ ! -f "$PTERO_DIR/.env" ]; then echo "❌ Error: Pterodactyl .env not found. Aborting." exit 1 fi get_env() { grep -w "$1" $PTERO_DIR/.env | cut -d '=' -f2 | tr -d '"' | tr -d "'" } ``` **Block 2: Variable Assignment** ```bash echo "Loading database credentials..." DB_HOST=$(get_env "DB_HOST") DB_PORT=$(get_env "DB_PORT") DB_NAME=$(get_env "DB_DATABASE") DB_USER=$(get_env "DB_USERNAME") DB_PASS=$(get_env "DB_PASSWORD") ``` **Block 3: SQL Payload for MODPACK_PLATFORM** ```bash SQL_PLATFORM="INSERT INTO egg_variables (egg_id, name, description, env_variable, default_value, user_viewable, user_editable, rules, created_at, updated_at) SELECT id, 'Modpack Platform', 'Detected platform (auto, curseforge, ftb, modrinth)', 'MODPACK_PLATFORM', 'auto', 1, 1, 'required|string|max:50', NOW(), NOW() FROM eggs WHERE NOT EXISTS ( SELECT 1 FROM egg_variables ev WHERE ev.egg_id = eggs.id AND ev.env_variable = 'MODPACK_PLATFORM' );" ``` **Block 4: SQL Payload for MODPACK_ID** ```bash SQL_ID="INSERT INTO egg_variables (egg_id, name, description, env_variable, default_value, user_viewable, user_editable, rules, created_at, updated_at) SELECT id, 'Modpack ID', 'Project ID for the platform', 'MODPACK_ID', '', 1, 1, 'nullable|string|max:191', NOW(), NOW() FROM eggs WHERE NOT EXISTS ( SELECT 1 FROM egg_variables ev WHERE ev.egg_id = eggs.id AND ev.env_variable = 'MODPACK_ID' );" ``` **Block 5: Execution & Error Handling** ```bash echo "Injecting Modpack Platform variable..." mysql -h"$DB_HOST" -P"$DB_PORT" -u"$DB_USER" -p"$DB_PASS" "$DB_NAME" -e "$SQL_PLATFORM" if [ $? -ne 0 ]; then echo "❌ Failed to inject MODPACK_PLATFORM. Aborting." exit 1 fi echo "Injecting Modpack ID variable..." mysql -h"$DB_HOST" -P"$DB_PORT" -u"$DB_USER" -p"$DB_PASS" "$DB_NAME" -e "$SQL_ID" echo "✅ Blueprint extension installed successfully! 🔥❄️" ``` --- ### remove.sh - Clean Uninstall Script **Location:** `/scripts/remove.sh` **Block 1: Setup & Deletion** ```bash #!/bin/bash # Blueprint Extension Remove Script PTERO_DIR="/var/www/pterodactyl" get_env() { grep -w "$1" $PTERO_DIR/.env | cut -d '=' -f2 | tr -d '"' | tr -d "'" } DB_NAME=$(get_env "DB_DATABASE") DB_USER=$(get_env "DB_USERNAME") DB_PASS=$(get_env "DB_PASSWORD") ``` **Block 2: Safely Execute Removal** ```bash echo "Removing database variables..." SQL_REMOVE="DELETE FROM egg_variables WHERE env_variable IN ('MODPACK_PLATFORM', 'MODPACK_ID');" mysql -u"$DB_USER" -p"$DB_PASS" "$DB_NAME" -e "$SQL_REMOVE" if [ $? -eq 0 ]; then echo "🗑️ Modpack variables safely removed." else echo "❌ Error removing database variables. Manual cleanup required." fi ``` **Note:** CASCADE foreign keys automatically clean server_variables table --- ## 3. BACKEND SERVICES (PHP/LARAVEL) ### ModpackDetector.php - File Scanning & Platform Detection **Location:** `/app/Services/Extensions/ModpackVersionChecker/ModpackDetector.php` **Block 1: Service Setup** ```php 'instance.json', 'modrinth' => 'modrinth.index.json', 'curseforge' => 'manifest.json', ]; } ``` **Block 2: File Scanning Logic** ```php public function detect(Server $server) { foreach (self::PLATFORMS as $type => $file) { // Check if file exists in server root if ($this->disk->exists($server->uuid . '/' . $file)) { return $this->processPlatform($type, $server, $file); } } return 'unknown'; } ``` **Block 3: CurseForge Extraction** ```php private function parseCurseForge($content) { $data = json_decode($content, true); return [ 'id' => $data['projectID'] ?? null, 'version' => $data['version'] ?? 'unknown' ]; } ``` **Block 4: FTB Extraction** ```php private function parseFTB($content) { $data = json_decode($content, true); return [ 'id' => $data['modpackId'] ?? null, 'version' => $data['versionId'] ?? 'unknown' ]; } ``` --- ### ModpackCacheService.php - Egg Variable Caching **Location:** `/app/Services/Extensions/ModpackVersionChecker/ModpackCacheService.php` **Block 1: Service Setup** ```php detector = $detector; } } ``` **Block 2: Reading the Cache** ```php public function getCachedPlatform(Server $server) { $platformVar = $server->variables() ->whereHas('variable', function ($query) { $query->where('env_variable', 'MODPACK_PLATFORM'); })->first(); return $platformVar ? $platformVar->server_value : 'auto'; } ``` **Block 3: The Detection Trigger** ```php public function resolvePlatform(Server $server) { $current = $this->getCachedPlatform($server); if ($current === 'auto') { $detected = $this->detector->detect($server); $this->updateCache($server, $detected['platform'], $detected['id']); return $detected['platform']; } return $current; } ``` **Block 4: Writing to Database (Caching)** ```php private function updateCache(Server $server, $platform, $id) { $server->variables()->whereHas('variable', fn($q) => $q->where('env_variable', 'MODPACK_PLATFORM') )->update(['server_value' => $platform]); $server->variables()->whereHas('variable', fn($q) => $q->where('env_variable', 'MODPACK_ID') )->update(['server_value' => $id]); } ``` --- ## 4. FRONTEND COMPONENTS (REACT/TYPESCRIPT) ### ModpackStatusBadge.tsx - React Component **Location:** `/resources/scripts/components/server/ModpackStatusBadge.tsx` **Block 1: Component Setup** ```tsx // resources/scripts/components/server/ModpackStatusBadge.tsx import React, { useState, useEffect } from 'react'; import getModpackStatus from '@/api/server/getModpackStatus'; export default ({ serverId }: { serverId: string }) => { const [status, setStatus] = useState('Checking...'); const [color, setColor] = useState('bg-yellow-500'); // Fetch logic goes here }; ``` **Block 2: Component Render** ```tsx // resources/scripts/components/server/ModpackStatusBadge.tsx (continued) return (

Modpack: {status}
); ``` **Note:** Complete implementation requires API endpoint for fetching status and re-scan trigger --- ## 5. API PROVIDER IMPLEMENTATIONS ### FtbApiService.php - FTB API Integration **Location:** `/app/Services/Extensions/ModpackVersionChecker/Providers/FtbApiService.php` ```php baseUrl}/modpack/{$modpackId}"); if ($response->successful()) { $versions = $response->json('versions'); // FTB versions are usually ordered; grab the first (newest) return $versions[0]['name'] ?? 'Unknown'; } return null; } } ``` **API Endpoint:** `https://api.modpacks.ch/public/modpack/{modpackId}` **Authentication:** None required (public API) **Notes:** - FTB returns version ID (integer) separately from version string - Requires two API calls for full version info - No rate limiting on public endpoints --- ### CurseForgeProvider.php - CurseForge API Integration **Location:** `/app/Services/Extensions/ModpackVersionChecker/Providers/CurseForgeProvider.php` **Structure:** ```php apiKey = $apiKey; } public function detectPlatform($serverPath) { // Check for manifest.json } public function getInstalledVersion($serverPath) { // Parse manifest.json } public function getLatestVersion($projectId) { // Query CurseForge API } public function compareVersions($installed, $latest) { // Semantic version comparison } } ``` **API Requirements:** - Requires API key (user-provided) - Store globally in admin panel - Graceful degradation if no key --- ### ModrinthProvider.php - Modrinth API Integration **Location:** `/app/Services/Extensions/ModpackVersionChecker/Providers/ModrinthProvider.php` **Structure:** ```php