$item['id'], 'set_id' => $setId, 'name' => $item['name'] ?? $classname, ]; } } // Insert sound sets into trax_songs (if table exists) if (DB::getSchemaBuilder()->hasTable('soundsets')) { DB::table('soundsets')->truncate(); foreach ($soundSets as $set) { DB::table('soundsets')->insert([ 'id' => $set['set_id'], 'name' => $set['name'], 'trackid' => $set['item_id'], ]); $inserted++; } } Log::info('[TraxService] Sound sets sync complete', [ 'inserted' => $inserted, ]); return [ 'inserted' => $inserted, 'total_sets' => count($soundSets), ]; } public function syncSoundtracks(): array { Log::info('[TraxService] Starting soundtracks sync'); $soundFiles = glob('/var/www/Gamedata/sounds/sound_machine_sample_*.mp3'); $existing = DB::table('soundtracks')->pluck('id')->toArray(); $inserted = 0; foreach ($soundFiles as $file) { $basename = basename($file, '.mp3'); preg_match('/sound_machine_sample_(\d+)/', $basename, $matches); if (isset($matches[1]) && ($matches[1] !== '' && $matches[1] !== '0')) { $sampleId = (int) $matches[1]; if (! in_array($sampleId, $existing)) { DB::table('soundtracks')->insert([ 'id' => $sampleId, 'code' => $basename, 'name' => 'Sample ' . $sampleId, 'author' => 'System', 'track' => '', 'length' => 0, ]); $inserted++; } } } Log::info('[TraxService] Soundtracks sync complete', [ 'inserted' => $inserted, ]); return [ 'inserted' => $inserted, 'total' => DB::table('soundtracks')->count(), 'samples' => count($soundFiles), ]; } public function getStats(): array { return [ 'soundtracks' => DB::table('soundtracks')->count(), 'sound_samples' => count(glob('/var/www/Gamedata/sounds/sound_machine_sample_*.mp3') ?: []), 'room_trax' => DB::table('room_trax')->count(), 'trax_playlist' => DB::table('trax_playlist')->count(), 'soundsets' => $this->countSoundSets(), ]; } private function countSoundSets(): int { $furnitureData = json_decode( file_get_contents('/var/www/Gamedata/config/FurnitureData.json'), true, ); $count = 0; foreach ($furnitureData['roomitemtypes']['furnitype'] ?? [] as $item) { if (str_starts_with($item['classname'] ?? '', 'sound_set')) { $count++; } } return $count; } public function importFromUrl(string $baseUrl): array { Log::info('[TraxService] Importing sounds from: ' . $baseUrl); $results = [ 'downloaded' => 0, 'failed' => 0, ]; $soundPath = '/var/www/Gamedata/sounds'; $soundUrl = rtrim($baseUrl, '/') . '/gamedata/sounds'; // Get list of sound samples from FurnitureData $furnitureData = json_decode( file_get_contents('/var/www/Gamedata/config/FurnitureData.json'), true, ); $sampleIds = []; foreach ($furnitureData['roomitemtypes']['furnitype'] ?? [] as $item) { if (str_starts_with($item['classname'] ?? '', 'sound_set')) { // Each sound set can have multiple samples for ($i = 0; $i < 200; $i++) { $sampleIds[] = $i; } } } $sampleIds = array_unique($sampleIds); foreach ($sampleIds as $id) { $filename = 'sound_machine_sample_' . $id . '.mp3'; $localFile = $soundPath . '/' . $filename; if (! file_exists($localFile)) { $url = $soundUrl . '/' . $filename; $content = @file_get_contents($url); if ($content && strlen($content) > 1000) { file_put_contents($localFile, $content); $results['downloaded']++; } else { $results['failed']++; } } } Log::info('[TraxService] Import complete', $results); return $results; } public function getTraxItems(): array { return DB::table('items_base') ->where('item_name', 'like', '%sound%') ->orWhere('item_name', 'like', '%trax%') ->orWhere('interaction_type', '=', 'sound') ->get() ->toArray(); } public function linkSoundMachine(): bool { // Make sure sound_machine has correct interaction type $machine = DB::table('items_base') ->where('item_name', 'sound_machine') ->first(); if ($machine) { DB::table('items_base') ->where('id', $machine->id) ->update(['interaction_type' => 'sound_machine']); Log::info('[TraxService] Sound machine linked'); return true; } return false; } }