713 lines
		
	
	
	
		
			21 KiB
		
	
	
	
		
			Lua
		
	
	
	
	
	
			
		
		
	
	
			713 lines
		
	
	
	
		
			21 KiB
		
	
	
	
		
			Lua
		
	
	
	
	
	
| local QBCore = exports['qb-core']:GetCoreObject()
 | |
| local PlayerData = {}
 | |
| local currentBooth = nil
 | |
| local isPlaying = false
 | |
| local currentVolume = Config.DefaultVolume
 | |
| local currentSong = nil
 | |
| local activeBooths = {}
 | |
| local isUIOpen = false
 | |
| local isDJBooth = false
 | |
| local nearestBooth = nil
 | |
| 
 | |
| -- Events
 | |
| RegisterNetEvent('QBCore:Client:OnPlayerLoaded', function()
 | |
|     PlayerData = QBCore.Functions.GetPlayerData()
 | |
|     
 | |
|     -- Frage Server nach aktiven DJ-Booths
 | |
|     TriggerServerEvent('dj:server:requestActiveDJs')
 | |
| end)
 | |
| 
 | |
| RegisterNetEvent('QBCore:Client:OnJobUpdate', function(JobInfo)
 | |
|     PlayerData.job = JobInfo
 | |
| end)
 | |
| 
 | |
| -- Key Mapping
 | |
| RegisterKeyMapping('opendj', 'Open DJ Menu', 'keyboard', Config.OpenMenuKey)
 | |
| 
 | |
| RegisterCommand('opendj', function()
 | |
|     if not CanUseDJScript() then
 | |
|         lib.notify({
 | |
|             title = 'DJ System',
 | |
|             description = 'Du hast keine Berechtigung das DJ System zu nutzen!',
 | |
|             type = 'error'
 | |
|         })
 | |
|         return
 | |
|     end
 | |
|     
 | |
|     if not isDJBooth then
 | |
|         lib.notify({
 | |
|             title = 'DJ System',
 | |
|             description = 'Du musst an einem DJ Pult stehen!',
 | |
|             type = 'error'
 | |
|         })
 | |
|         return
 | |
|     end
 | |
|     
 | |
|     OpenDJInterface()
 | |
| end)
 | |
| 
 | |
| -- Musik abspielen (von Server empfangen)
 | |
| RegisterNetEvent('dj:client:playMusic', function(data)
 | |
|     -- Speichere Booth-Informationen
 | |
|     activeBooths[data.booth.name] = {
 | |
|         url = data.url,
 | |
|         title = data.title,
 | |
|         volume = data.volume,
 | |
|         coords = data.booth.coords,
 | |
|         range = data.range
 | |
|     }
 | |
|     
 | |
|     -- Prüfe ob Spieler in Reichweite ist
 | |
|     local playerCoords = GetEntityCoords(PlayerPedId())
 | |
|     local distance = #(playerCoords - data.booth.coords)
 | |
|     
 | |
|     if distance <= data.range then
 | |
|         -- Berechne Lautstärke basierend auf Distanz
 | |
|         local volumeMultiplier = 1.0 - (distance / data.range)
 | |
|         local adjustedVolume = math.floor(data.volume * volumeMultiplier)
 | |
|         
 | |
|         -- Spiele Musik ab
 | |
|         SendNUIMessage({
 | |
|             type = 'playMusic',
 | |
|             url = data.url,
 | |
|             volume = adjustedVolume,
 | |
|             title = data.title
 | |
|         })
 | |
|         
 | |
|         -- Setze lokale Variablen
 | |
|         currentBooth = {
 | |
|             name = data.booth.name,
 | |
|             coords = data.booth.coords
 | |
|         }
 | |
|         isPlaying = true
 | |
|         currentSong = {
 | |
|             title = data.title,
 | |
|             url = data.url
 | |
|         }
 | |
|         
 | |
|         -- Zeige Benachrichtigung
 | |
|         lib.notify({
 | |
|             title = 'DJ System',
 | |
|             description = 'Spielt: ' .. data.title,
 | |
|             type = 'info'
 | |
|         })
 | |
|     end
 | |
| end)
 | |
| 
 | |
| -- Musik stoppen (von Server empfangen)
 | |
| RegisterNetEvent('dj:client:stopMusic', function(boothName)
 | |
|     -- Entferne Booth-Informationen
 | |
|     if activeBooths[boothName] then
 | |
|         activeBooths[boothName] = nil
 | |
|     end
 | |
|     
 | |
|     -- Wenn der Spieler diese Musik hört, stoppe sie
 | |
|     if currentBooth and currentBooth.name == boothName then
 | |
|         SendNUIMessage({
 | |
|             type = 'stopMusic'
 | |
|         })
 | |
|         
 | |
|         currentBooth = nil
 | |
|         isPlaying = false
 | |
|         currentSong = nil
 | |
|         
 | |
|         lib.notify({
 | |
|             title = 'DJ System',
 | |
|             description = 'Musik gestoppt',
 | |
|             type = 'info'
 | |
|         })
 | |
|     end
 | |
| end)
 | |
| 
 | |
| -- Lautstärke ändern (von Server empfangen)
 | |
| RegisterNetEvent('dj:client:setVolume', function(data)
 | |
|     -- Aktualisiere Booth-Informationen
 | |
|     if activeBooths[data.booth.name] then
 | |
|         activeBooths[data.booth.name].volume = data.volume
 | |
|         activeBooths[data.booth.name].range = data.range
 | |
|     end
 | |
|     
 | |
|     -- Wenn der Spieler diese Musik hört, ändere die Lautstärke
 | |
|     if currentBooth and currentBooth.name == data.booth.name then
 | |
|         -- Berechne Lautstärke basierend auf Distanz
 | |
|         local playerCoords = GetEntityCoords(PlayerPedId())
 | |
|         local distance = #(playerCoords - data.booth.coords)
 | |
|         local volumeMultiplier = 1.0 - (distance / data.range)
 | |
|         local adjustedVolume = math.floor(data.volume * volumeMultiplier)
 | |
|         
 | |
|         SendNUIMessage({
 | |
|             type = 'setVolume',
 | |
|             volume = adjustedVolume
 | |
|         })
 | |
|         
 | |
|         currentVolume = data.volume
 | |
|     end
 | |
| end)
 | |
| 
 | |
| -- Empfange aktive DJs
 | |
| RegisterNetEvent('dj:client:receiveActiveDJs', function(booths)
 | |
|     activeBooths = booths
 | |
|     
 | |
|     -- Prüfe ob Spieler in Reichweite eines aktiven DJ-Booths ist
 | |
|     local playerCoords = GetEntityCoords(PlayerPedId())
 | |
|     
 | |
|     for boothName, boothData in pairs(activeBooths) do
 | |
|         local distance = #(playerCoords - boothData.coords)
 | |
|         
 | |
|         if distance <= boothData.range then
 | |
|             -- Berechne Lautstärke basierend auf Distanz
 | |
|             local volumeMultiplier = 1.0 - (distance / boothData.range)
 | |
|             local adjustedVolume = math.floor(boothData.volume * volumeMultiplier)
 | |
|             
 | |
|             -- Spiele Musik ab
 | |
|             SendNUIMessage({
 | |
|                 type = 'playMusic',
 | |
|                 url = boothData.url,
 | |
|                 volume = adjustedVolume,
 | |
|                 title = boothData.title
 | |
|             })
 | |
|             
 | |
|             currentBooth = {
 | |
|                 name = boothName,
 | |
|                 coords = boothData.coords
 | |
|             }
 | |
|             isPlaying = true
 | |
|             currentSong = {
 | |
|                 title = boothData.title,
 | |
|                 url = boothData.url
 | |
|             }
 | |
|             
 | |
|             lib.notify({
 | |
|                 title = 'DJ System',
 | |
|                 description = 'Spielt: ' .. boothData.title,
 | |
|                 type = 'info'
 | |
|             })
 | |
|             
 | |
|             break
 | |
|         end
 | |
|     end
 | |
| end)
 | |
| 
 | |
| RegisterNUICallback('djInterfaceClosed', function(data, cb)
 | |
|     SetNuiFocus(false, false)
 | |
|     isUIOpen = false
 | |
|     
 | |
|     -- Kurze Verzögerung, um sicherzustellen, dass alle Animationen abgeschlossen sind
 | |
|     Wait(100)
 | |
|     
 | |
|     -- Aktiviere alle Controls wieder
 | |
|     EnableAllControlActions(0)
 | |
|     
 | |
|     -- Musik NICHT stoppen, wenn stopMusic nicht explizit true ist
 | |
|     if data.stopMusic then
 | |
|         -- Stoppe Musik nur wenn explizit angefordert
 | |
|         if currentBooth then
 | |
|             TriggerServerEvent('dj:server:stopMusic', currentBooth.name)
 | |
|         end
 | |
|     end
 | |
|     
 | |
|     cb('ok')
 | |
| end)
 | |
| 
 | |
| 
 | |
| RegisterNUICallback('deckStateChanged', function(data, cb)
 | |
|     if Config.Debug then
 | |
|         print(string.format('[DJ System] Deck %s %s: %s', 
 | |
|             data.deck, 
 | |
|             data.isPlaying and 'playing' or 'stopped',
 | |
|             data.track and data.track.title or 'No track'
 | |
|         ))
 | |
|     end
 | |
|     
 | |
|     -- Wenn Deck A oder B abspielt, sende an Server
 | |
|     if data.isPlaying and data.track then
 | |
|         PlayMusicAsDJ(data.track.title, data.track.url, currentVolume)
 | |
|     end
 | |
|     
 | |
|     cb('ok')
 | |
| end)
 | |
| 
 | |
| RegisterNUICallback('volumeChanged', function(data, cb)
 | |
|     if data.volume then
 | |
|         SetVolumeAsDJ(data.volume)
 | |
|     end
 | |
|     cb('ok')
 | |
| end)
 | |
| 
 | |
| RegisterNUICallback('stopMusic', function(data, cb)
 | |
|     StopMusicAsDJ()
 | |
|     cb('ok')
 | |
| end)
 | |
| 
 | |
| RegisterNUICallback('audioError', function(data, cb)
 | |
|     lib.notify({
 | |
|         title = 'DJ System',
 | |
|         description = 'Audio Fehler: ' .. (data.error or 'Unbekannter Fehler'),
 | |
|         type = 'error'
 | |
|     })
 | |
|     cb('ok')
 | |
| end)
 | |
| 
 | |
| RegisterNUICallback('songEnded', function(data, cb)
 | |
|     -- Wenn ein Song endet, kann hier Playlist-Logik implementiert werden
 | |
|     if Config.Debug then
 | |
|         print('[DJ System] Song ended')
 | |
|     end
 | |
|     cb('ok')
 | |
| end)
 | |
| 
 | |
| RegisterNUICallback('loadTrack', function(data, cb)
 | |
|     if data.deck and data.track then
 | |
|         -- Lade Track in Deck
 | |
|         if data.deck == "A" or data.deck == "B" then
 | |
|             -- Hier könntest du zusätzliche Logik hinzufügen
 | |
|             cb({success = true})
 | |
|         else
 | |
|             cb({success = false, error = "Ungültiges Deck"})
 | |
|         end
 | |
|     else
 | |
|         cb({success = false, error = "Fehlende Daten"})
 | |
|     end
 | |
| end)
 | |
| 
 | |
| RegisterNUICallback('playTrack', function(data, cb)
 | |
|     if data.deck and data.track then
 | |
|         -- Spiele Track ab
 | |
|         PlayMusicAsDJ(data.track.title, data.track.url, currentVolume)
 | |
|         cb({success = true})
 | |
|     else
 | |
|         cb({success = false, error = "Fehlende Daten"})
 | |
|     end
 | |
| end)
 | |
| 
 | |
| RegisterNUICallback('getPlaylists', function(data, cb)
 | |
|     -- Hole Playlists vom Server
 | |
|     QBCore.Functions.TriggerCallback('dj:server:getPlaylists', function(playlists)
 | |
|         cb({success = true, playlists = playlists})
 | |
|     end)
 | |
| end)
 | |
| 
 | |
| RegisterNUICallback('createPlaylist', function(data, cb)
 | |
|     if data.name then
 | |
|         -- Erstelle Playlist
 | |
|         TriggerServerEvent('dj:server:createPlaylist', data.name, data.description, data.isPublic)
 | |
|         cb({success = true})
 | |
|     else
 | |
|         cb({success = false, error = "Fehlender Name"})
 | |
|     end
 | |
| end)
 | |
| 
 | |
| RegisterNUICallback('addToPlaylist', function(data, cb)
 | |
|     if data.playlistId and data.track then
 | |
|         -- Füge Track zu Playlist hinzu
 | |
|         TriggerServerEvent('dj:server:addSongToPlaylist', data.playlistId, data.track)
 | |
|         cb({success = true})
 | |
|     else
 | |
|         cb({success = false, error = "Fehlende Daten"})
 | |
|     end
 | |
| end)
 | |
| 
 | |
| RegisterNUICallback('getSessionHistory', function(data, cb)
 | |
|     -- Hole Session-Historie vom Server
 | |
|     QBCore.Functions.TriggerCallback('dj:server:getSessionHistory', function(history)
 | |
|         cb({success = true, history = history})
 | |
|     end, data.limit)
 | |
| end)
 | |
| 
 | |
| -- Functions
 | |
| function CanUseDJScript()
 | |
|     if not Config.UseJobRestriction then
 | |
|         return true
 | |
|     end
 | |
|     
 | |
|     if not PlayerData.job then
 | |
|         return false
 | |
|     end
 | |
|     
 | |
|     for _, job in pairs(Config.AllowedJobs) do
 | |
|         if PlayerData.job.name == job then
 | |
|             return true
 | |
|         end
 | |
|     end
 | |
|     
 | |
|     return false
 | |
| end
 | |
| 
 | |
| function OpenDJInterface()
 | |
|     if not isDJBooth then
 | |
|         lib.notify({
 | |
|             title = 'DJ System',
 | |
|             description = 'Du musst an einem DJ Pult stehen',
 | |
|             type = 'error'
 | |
|         })
 | |
|         return
 | |
|     end
 | |
|     
 | |
|     SetNuiFocus(true, true)
 | |
|     SendNUIMessage({
 | |
|         type = 'showDJInterface'
 | |
|     })
 | |
|     
 | |
|     isUIOpen = true
 | |
|     
 | |
|     -- Disable controls while UI is open
 | |
|     CreateThread(function()
 | |
|         while isUIOpen do
 | |
|             DisableAllControlActions(0)
 | |
|             EnableControlAction(0, 1, true) -- Mouse look
 | |
|             EnableControlAction(0, 2, true) -- Mouse look
 | |
|             EnableControlAction(0, 3, true) -- Mouse movement
 | |
|             EnableControlAction(0, 4, true) -- Mouse movement
 | |
|             EnableControlAction(0, 5, true) -- Mouse wheel
 | |
|             EnableControlAction(0, 6, true) -- Mouse wheel
 | |
|             Wait(0)
 | |
|         end
 | |
|     end)
 | |
| end
 | |
| 
 | |
| function PlayMusicAsDJ(title, url, volume)
 | |
|     if not nearestBooth then
 | |
|         lib.notify({
 | |
|             title = 'DJ System',
 | |
|             description = 'Du musst an einem DJ-Pult stehen!',
 | |
|             type = 'error'
 | |
|         })
 | |
|         return
 | |
|     end
 | |
|     
 | |
|     -- Bereinige YouTube URL von Playlist-Parametern
 | |
|     local cleanUrl = url
 | |
|     if string.find(url, "youtube") then
 | |
|         cleanUrl = string.gsub(url, "&list=.-$", "")
 | |
|         cleanUrl = string.gsub(cleanUrl, "&start_radio=.-$", "")
 | |
|         cleanUrl = string.gsub(cleanUrl, "&index=.-$", "")
 | |
|     end
 | |
|     
 | |
|     -- Sende an Server zur Synchronisation
 | |
|     TriggerServerEvent('dj:server:playMusic', {
 | |
|         title = title,
 | |
|         url = cleanUrl,
 | |
|         volume = volume or Config.DefaultVolume,
 | |
|         booth = {
 | |
|             name = nearestBooth,
 | |
|             coords = Config.DJBooths[nearestBooth].coords
 | |
|         },
 | |
|         range = CalculateRange(volume or Config.DefaultVolume)
 | |
|     })
 | |
|     
 | |
|     -- Lokale Variablen aktualisieren
 | |
|     isPlaying = true
 | |
|     currentVolume = volume or Config.DefaultVolume
 | |
|     currentSong = {
 | |
|         title = title,
 | |
|         url = cleanUrl
 | |
|     }
 | |
|     currentBooth = {
 | |
|         name = nearestBooth,
 | |
|         coords = Config.DJBooths[nearestBooth].coords
 | |
|     }
 | |
| end
 | |
| 
 | |
| function StopMusicAsDJ()
 | |
|     if not nearestBooth then
 | |
|         lib.notify({
 | |
|             title = 'DJ System',
 | |
|             description = 'Du musst an einem DJ-Pult stehen!',
 | |
|             type = 'error'
 | |
|         })
 | |
|         return
 | |
|     end
 | |
|     
 | |
|     -- Sende an Server zur Synchronisation
 | |
|     TriggerServerEvent('dj:server:stopMusic', nearestBooth)
 | |
|     
 | |
|     -- Lokale Variablen aktualisieren
 | |
|     isPlaying = false
 | |
|     currentSong = nil
 | |
|     currentBooth = nil
 | |
| end
 | |
| 
 | |
| function SetVolumeAsDJ(volume)
 | |
|     if not nearestBooth then
 | |
|         lib.notify({
 | |
|             title = 'DJ System',
 | |
|             description = 'Du musst an einem DJ-Pult stehen!',
 | |
|             type = 'error'
 | |
|         })
 | |
|         return
 | |
|     end
 | |
|     
 | |
|     -- Sende an Server zur Synchronisation
 | |
|     TriggerServerEvent('dj:server:setVolume', {
 | |
|         volume = volume,
 | |
|         booth = {
 | |
|             name = nearestBooth,
 | |
|             coords = Config.DJBooths[nearestBooth].coords
 | |
|         },
 | |
|         range = CalculateRange(volume)
 | |
|     })
 | |
|     
 | |
|     -- Lokale Variablen aktualisieren
 | |
|     currentVolume = volume
 | |
| end
 | |
| 
 | |
| function CalculateRange(volume)
 | |
|     if not nearestBooth or not Config.DJBooths[nearestBooth] then return 30.0 end
 | |
|     
 | |
|     local booth = Config.DJBooths[nearestBooth]
 | |
|     local baseRange = booth.range or 30.0
 | |
|     local maxRange = booth.maxRange or 50.0
 | |
|     local volumePercent = volume / 100
 | |
|     
 | |
|     return baseRange + ((maxRange - baseRange) * volumePercent)
 | |
| end
 | |
| 
 | |
| -- Regelmäßige Prüfung der Distanz zu DJ-Booths und aktiven Musiken
 | |
| CreateThread(function()
 | |
|     while true do
 | |
|         Wait(Config.DistanceVolume and Config.DistanceVolume.updateInterval or 1000)
 | |
|         
 | |
|         local playerCoords = GetEntityCoords(PlayerPedId())
 | |
|         local foundBooth = false
 | |
|         nearestBooth = nil
 | |
|         local nearestDistance = 999999.9
 | |
|         
 | |
|         -- Prüfe Nähe zu DJ-Booths
 | |
|         for boothName, booth in pairs(Config.DJBooths) do
 | |
|             local distance = #(playerCoords - booth.coords)
 | |
|             
 | |
|             -- Finde das nächste DJ-Booth
 | |
|             if distance < nearestDistance then
 | |
|                 nearestDistance = distance
 | |
|                 nearestBooth = boothName
 | |
|             end
 | |
|             
 | |
|             -- Prüfe ob Spieler an einem DJ-Booth steht
 | |
|             if distance <= 2.0 then
 | |
|                 foundBooth = true
 | |
|                 break
 | |
|             end
 | |
|         end
 | |
|         
 | |
|         isDJBooth = foundBooth
 | |
|         
 | |
|         -- Prüfe Distanz zu aktiven Musiken
 | |
|         if not isPlaying and next(activeBooths) then
 | |
|             -- Spieler hört keine Musik, prüfe ob er in Reichweite eines aktiven DJ-Booths ist
 | |
|             for boothName, boothData in pairs(activeBooths) do
 | |
|                 local distance = #(playerCoords - boothData.coords)
 | |
|                 
 | |
|                 if distance <= boothData.range then
 | |
|                     -- Berechne Lautstärke basierend auf Distanz
 | |
|                     local volumeMultiplier = 1.0 - (distance / boothData.range)
 | |
|                     local adjustedVolume = math.floor(boothData.volume * volumeMultiplier)
 | |
|                     
 | |
|                     -- Spiele Musik ab
 | |
|                     SendNUIMessage({
 | |
|                         type = 'playMusic',
 | |
|                         url = boothData.url,
 | |
|                         volume = adjustedVolume,
 | |
|                         title = boothData.title
 | |
|                     })
 | |
|                     
 | |
|                     currentBooth = {
 | |
|                         name = boothName,
 | |
|                         coords = boothData.coords
 | |
|                     }
 | |
|                     isPlaying = true
 | |
|                     currentSong = {
 | |
|                         title = boothData.title,
 | |
|                         url = boothData.url
 | |
|                     }
 | |
|                     
 | |
|                     lib.notify({
 | |
|                         title = 'DJ System',
 | |
|                         description = 'Spielt: ' .. boothData.title,
 | |
|                         type = 'info'
 | |
|                     })
 | |
|                     
 | |
|                     break
 | |
|                 end
 | |
|             end
 | |
|         elseif isPlaying and currentBooth then
 | |
|             -- Spieler hört Musik, prüfe ob er noch in Reichweite ist
 | |
|             local boothData = activeBooths[currentBooth.name]
 | |
|             
 | |
|             if boothData then
 | |
|                 local distance = #(playerCoords - boothData.coords)
 | |
|                 
 | |
|                 if distance > boothData.range then
 | |
|                     -- Spieler hat Reichweite verlassen, stoppe Musik
 | |
|                     SendNUIMessage({
 | |
|                         type = 'stopMusic'
 | |
|                     })
 | |
|                     
 | |
|                     currentBooth = nil
 | |
|                     isPlaying = false
 | |
|                     currentSong = nil
 | |
|                     
 | |
|                     lib.notify({
 | |
|                         title = 'DJ System',
 | |
|                         description = 'Musik außer Reichweite',
 | |
|                         type = 'info'
 | |
|                     })
 | |
|                 else
 | |
|                     -- Spieler ist noch in Reichweite, passe Lautstärke an
 | |
|                     local volumeMultiplier = 1.0 - (distance / boothData.range)
 | |
|                     local adjustedVolume = math.floor(boothData.volume * volumeMultiplier)
 | |
|                     
 | |
|                     SendNUIMessage({
 | |
|                         type = 'setVolume',
 | |
|                         volume = adjustedVolume
 | |
|                     })
 | |
|                 end
 | |
|             else
 | |
|                 -- Booth existiert nicht mehr, stoppe Musik
 | |
|                 SendNUIMessage({
 | |
|                     type = 'stopMusic'
 | |
|                 })
 | |
|                 
 | |
|                 currentBooth = nil
 | |
|                 isPlaying = false
 | |
|                 currentSong = nil
 | |
|             end
 | |
|         end
 | |
|     end
 | |
| end)
 | |
| 
 | |
| -- DJ Booth Blips und Interaktionen
 | |
| CreateThread(function()
 | |
|     -- Erstelle Blips für DJ-Booths
 | |
|     for boothName, booth in pairs(Config.DJBooths) do
 | |
|         local blip = AddBlipForCoord(booth.coords)
 | |
|         SetBlipSprite(blip, 614)
 | |
|         SetBlipDisplay(blip, 4)
 | |
|         SetBlipScale(blip, 0.7)
 | |
|         SetBlipColour(blip, 47)
 | |
|         SetBlipAsShortRange(blip, true)
 | |
|         BeginTextCommandSetBlipName("STRING")
 | |
|         AddTextComponentString("DJ Booth - " .. boothName)
 | |
|         EndTextCommandSetBlipName(blip)
 | |
|     end
 | |
|     
 | |
|     -- Erstelle Interaktionspunkte für DJ-Booths
 | |
|     for boothName, booth in pairs(Config.DJBooths) do
 | |
|         exports['qb-target']:AddBoxZone("dj_booth_" .. boothName, booth.coords, 1.5, 1.5, {
 | |
|             name = "dj_booth_" .. boothName,
 | |
|             heading = 0,
 | |
|             debugPoly = Config.Debug,
 | |
|             minZ = booth.coords.z - 1.0,
 | |
|             maxZ = booth.coords.z + 1.0
 | |
|         }, {
 | |
|             options = {
 | |
|                 {
 | |
|                     type = "client",
 | |
|                     event = "dj:client:openDJMenu",
 | |
|                     icon = "fas fa-music",
 | |
|                     label = "DJ System öffnen",
 | |
|                     boothName = boothName,
 | |
|                     job = Config.UseJobRestriction and Config.AllowedJobs or nil
 | |
|                 }
 | |
|             },
 | |
|             distance = 2.0
 | |
|         })
 | |
|     end
 | |
| end)
 | |
| 
 | |
| -- Event für Target-Integration
 | |
| RegisterNetEvent('dj:client:openDJMenu', function(data)
 | |
|     nearestBooth = data.boothName
 | |
|     isDJBooth = true
 | |
|     OpenDJInterface()
 | |
| end)
 | |
| 
 | |
| -- Debug
 | |
| if Config.Debug then
 | |
|     RegisterCommand('djdebug', function()
 | |
|         print('--- DJ SYSTEM DEBUG ---')
 | |
|         print('isPlaying:', isPlaying)
 | |
|         print('isDJBooth:', isDJBooth)
 | |
|         print('nearestBooth:', nearestBooth)
 | |
|         print('currentBooth:', currentBooth and currentBooth.name or 'nil')
 | |
|         print('currentVolume:', currentVolume)
 | |
|         print('currentSong:', currentSong and currentSong.title or 'nil')
 | |
|         print('activeBooths:')
 | |
|         for boothName, boothData in pairs(activeBooths) do
 | |
|             print('  -', boothName, boothData.title, boothData.volume)
 | |
|         end
 | |
|     end)
 | |
| end
 | |
| 
 | |
| function OpenDJInterface()
 | |
|     if not isDJBooth then
 | |
|         lib.notify({
 | |
|             title = 'DJ System',
 | |
|             description = 'Du musst an einem DJ Pult stehen',
 | |
|             type = 'error'
 | |
|         })
 | |
|         return
 | |
|     end
 | |
|     
 | |
|     SetNuiFocus(true, true)
 | |
|     SendNUIMessage({
 | |
|         type = 'showDJInterface',
 | |
|         center = true, -- Hinzugefügt: Zentriere das Interface
 | |
|         reset = true   -- Hinzugefügt: Setze Position zurück
 | |
|     })
 | |
|     
 | |
|     isUIOpen = true
 | |
|     
 | |
|     -- Disable controls while UI is open
 | |
|     CreateThread(function()
 | |
|         while isUIOpen do
 | |
|             DisableAllControlActions(0)
 | |
|             EnableControlAction(0, 1, true) -- Mouse look
 | |
|             EnableControlAction(0, 2, true) -- Mouse look
 | |
|             EnableControlAction(0, 3, true) -- Mouse movement
 | |
|             EnableControlAction(0, 4, true) -- Mouse movement
 | |
|             EnableControlAction(0, 5, true) -- Mouse wheel
 | |
|             EnableControlAction(0, 6, true) -- Mouse wheel
 | |
|             Wait(0)
 | |
|         end
 | |
|     end)
 | |
| end
 | |
| 
 | |
| 
 | |
| -- Callback-Handler für NUI
 | |
| RegisterNUICallback('callback', function(data, cb)
 | |
|     if data.callbackId then
 | |
|         SendNUIMessage({
 | |
|             type = 'callbackResponse',
 | |
|             callbackId = data.callbackId,
 | |
|             response = data.response or {}
 | |
|         })
 | |
|     end
 | |
|     cb('ok')
 | |
| end)
 | |
| 
 | |
| -- Verbesserte Error-Handling
 | |
| RegisterNUICallback('error', function(data, cb)
 | |
|     print("DJ System Error: " .. (data.error or "Unknown error"))
 | |
|     cb('ok')
 | |
|     
 | |
|     -- Benachrichtige Spieler
 | |
|     lib.notify({
 | |
|         title = 'DJ System Error',
 | |
|         description = data.error or "Ein unbekannter Fehler ist aufgetreten",
 | |
|         type = 'error'
 | |
|     })
 | |
| end)
 | |
| 
 | |
| -- Debug-Funktion für NUI-Status
 | |
| function DebugNUIStatus()
 | |
|     local nuiFocus = {GetNuiFocus()}
 | |
|     print("NUI Focus:", json.encode(nuiFocus))
 | |
|     print("isUIOpen:", isUIOpen)
 | |
|     print("isDJBooth:", isDJBooth)
 | |
|     print("nearestBooth:", nearestBooth)
 | |
| end
 | |
| 
 | |
| -- Debug-Befehl
 | |
| RegisterCommand('djdebug', function()
 | |
|     DebugNUIStatus()
 | |
| end, false)
 | 
