1
0
Fork 0
forked from Simnation/Main
This commit is contained in:
Nordi98 2025-08-03 16:51:12 +02:00
parent 0e29315dd1
commit e0a3b21c61
7 changed files with 1463 additions and 0 deletions

View file

@ -0,0 +1,587 @@
local QBCore = exports['qb-core']:GetCoreObject()
local PlayerData = {}
local currentDJBooth = nil
local isPlaying = false
local currentVolume = Config.DefaultVolume
local currentSong = nil
local playlists = {}
local currentPlaylist = nil
local currentSongIndex = 1
-- Events
RegisterNetEvent('QBCore:Client:OnPlayerLoaded', function()
PlayerData = QBCore.Functions.GetPlayerData()
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
local nearbyBooth = GetNearbyDJBooth()
if nearbyBooth then
currentDJBooth = nearbyBooth
OpenDJMenu()
else
lib.notify({
title = 'DJ System',
description = 'Du bist nicht in der Nähe einer DJ Booth!',
type = 'error'
})
end
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 GetNearbyDJBooth()
local playerCoords = GetEntityCoords(PlayerPedId())
for i, booth in pairs(Config.DJBooths) do
local distance = #(playerCoords - booth.coords)
if distance <= 3.0 then
return booth
end
end
return nil
end
function OpenDJMenu()
TriggerServerEvent('dj:server:getPlaylists')
local options = {
{
title = 'YouTube Song abspielen',
description = 'Spiele einen Song von YouTube ab',
icon = 'fab fa-youtube',
onSelect = function()
OpenYouTubeMenu()
end
},
{
title = 'Direkte URL abspielen',
description = 'Spiele einen Song von einer direkten URL ab',
icon = 'play',
onSelect = function()
OpenDirectUrlMenu()
end
},
{
title = 'Musik stoppen',
description = 'Stoppe die aktuelle Musik',
icon = 'stop',
onSelect = function()
StopMusic()
end
},
{
title = 'Lautstärke ändern',
description = 'Aktuelle Lautstärke: ' .. currentVolume .. '%',
icon = 'volume-up',
onSelect = function()
OpenVolumeMenu()
end
},
{
title = 'Playlists verwalten',
description = 'Erstelle und verwalte Playlists',
icon = 'list',
onSelect = function()
OpenPlaylistMenu()
end
}
}
if isPlaying and currentSong then
table.insert(options, 2, {
title = 'Aktueller Song',
description = currentSong.title,
icon = 'music',
disabled = true
})
end
lib.registerContext({
id = 'dj_main_menu',
title = 'DJ System - ' .. currentDJBooth.name,
options = options
})
lib.showContext('dj_main_menu')
end
function OpenYouTubeMenu()
local input = lib.inputDialog('YouTube Song abspielen', {
{type = 'input', label = 'Song Titel', placeholder = 'z.B. Daft Punk - One More Time'},
{type = 'input', label = 'YouTube URL', placeholder = 'https://www.youtube.com/watch?v=...'}
})
if input and input[1] and input[2] then
if not IsValidYouTubeUrl(input[2]) then
lib.notify({
title = 'DJ System',
description = 'Ungültige YouTube URL!',
type = 'error'
})
return
end
lib.notify({
title = 'DJ System',
description = 'YouTube URL wird konvertiert, bitte warten...',
type = 'info'
})
PlayMusic(input[1], input[2])
end
end
function OpenDirectUrlMenu()
local input = lib.inputDialog('Direkte URL abspielen', {
{type = 'input', label = 'Song Titel', placeholder = 'Titel des Songs'},
{type = 'input', label = 'Direkte MP3/Audio URL', placeholder = 'https://example.com/song.mp3'}
})
if input and input[1] and input[2] then
PlayMusic(input[1], input[2])
end
end
function IsValidYouTubeUrl(url)
local patterns = {
"youtube%.com/watch%?v=",
"youtu%.be/",
"youtube%.com/embed/"
}
for _, pattern in ipairs(patterns) do
if string.match(url, pattern) then
return true
end
end
return false
end
function OpenVolumeMenu()
local input = lib.inputDialog('Lautstärke einstellen', {
{
type = 'slider',
label = 'Lautstärke (%)',
description = 'Höhere Lautstärke = größere Reichweite',
default = currentVolume,
min = 0,
max = Config.MaxVolume,
step = 5
}
})
if input and input[1] then
SetVolume(input[1])
end
end
function OpenPlaylistMenu()
local options = {
{
title = 'Neue Playlist erstellen',
description = 'Erstelle eine neue Playlist',
icon = 'plus',
onSelect = function()
CreateNewPlaylist()
end
}
}
for _, playlist in pairs(playlists) do
table.insert(options, {
title = playlist.name,
description = #playlist.songs .. ' Songs',
icon = 'music',
onSelect = function()
OpenPlaylistOptions(playlist)
end
})
end
lib.registerContext({
id = 'playlist_menu',
title = 'Playlist Verwaltung',
menu = 'dj_main_menu',
options = options
})
lib.showContext('playlist_menu')
end
function CreateNewPlaylist()
local input = lib.inputDialog('Neue Playlist', {
{type = 'input', label = 'Playlist Name', placeholder = 'Meine YouTube Playlist'}
})
if input and input[1] then
TriggerServerEvent('dj:server:createPlaylist', input[1])
end
end
function OpenPlaylistOptions(playlist)
local options = {
{
title = 'Playlist abspielen',
description = 'Spiele alle Songs der Playlist ab',
icon = 'play',
onSelect = function()
PlayPlaylist(playlist)
end
},
{
title = 'YouTube Song hinzufügen',
description = 'Füge einen YouTube Song zur Playlist hinzu',
icon = 'fab fa-youtube',
onSelect = function()
AddYouTubeSongToPlaylist(playlist)
end
},
{
title = 'Direkten Song hinzufügen',
description = 'Füge einen Song per direkter URL hinzu',
icon = 'plus',
onSelect = function()
AddDirectSongToPlaylist(playlist)
end
},
{
title = 'Songs anzeigen',
description = 'Zeige alle Songs in der Playlist',
icon = 'list',
onSelect = function()
ShowPlaylistSongs(playlist)
end
},
{
title = 'Playlist löschen',
description = 'Lösche diese Playlist',
icon = 'trash',
onSelect = function()
DeletePlaylist(playlist)
end
}
}
lib.registerContext({
id = 'playlist_options',
title = playlist.name,
menu = 'playlist_menu',
options = options
})
lib.showContext('playlist_options')
end
function AddYouTubeSongToPlaylist(playlist)
local input = lib.inputDialog('YouTube Song hinzufügen', {
{type = 'input', label = 'Song Titel', placeholder = 'z.B. Avicii - Levels'},
{type = 'input', label = 'YouTube URL', placeholder = 'https://www.youtube.com/watch?v=...'}
})
if input and input[1] and input[2] then
if not IsValidYouTubeUrl(input[2]) then
lib.notify({
title = 'DJ System',
description = 'Ungültige YouTube URL!',
type = 'error'
})
return
end
TriggerServerEvent('dj:server:addSongToPlaylist', playlist.id, {
title = input[1],
url = input[2]
})
end
end
function AddDirectSongToPlaylist(playlist)
local input = lib.inputDialog('Direkten Song hinzufügen', {
{type = 'input', label = 'Song Titel', placeholder = 'Titel des Songs'},
{type = 'input', label = 'Direkte URL', placeholder = 'https://example.com/song.mp3'}
})
if input and input[1] and input[2] then
TriggerServerEvent('dj:server:addSongToPlaylist', playlist.id, {
title = input[1],
url = input[2]
})
end
end
function PlayMusic(title, url)
if not currentDJBooth then return end
currentSong = {title = title, url = url}
isPlaying = true
TriggerServerEvent('dj:server:playMusic', {
title = title,
url = url,
volume = currentVolume,
booth = currentDJBooth,
range = CalculateRange()
})
lib.notify({
title = 'DJ System',
description = 'Lade: ' .. title,
type = 'info'
})
end
function StopMusic()
if not isPlaying then
lib.notify({
title = 'DJ System',
description = 'Es läuft gerade keine Musik!',
type = 'error'
})
return
end
isPlaying = false
currentSong = nil
currentPlaylist = nil
TriggerServerEvent('dj:server:stopMusic', currentDJBooth)
lib.notify({
title = 'DJ System',
description = 'Musik gestoppt',
type = 'success'
})
end
function SetVolume(volume)
currentVolume = volume
if isPlaying then
TriggerServerEvent('dj:server:setVolume', {
volume = volume,
booth = currentDJBooth,
range = CalculateRange()
})
end
lib.notify({
title = 'DJ System',
description = 'Lautstärke auf ' .. volume .. '% gesetzt',
type = 'success'
})
end
function CalculateRange()
local baseRange = currentDJBooth.range
local maxRange = currentDJBooth.maxRange
local volumePercent = currentVolume / 100
return baseRange + ((maxRange - baseRange) * volumePercent)
end
function PlayPlaylist(playlist)
if #playlist.songs == 0 then
lib.notify({
title = 'DJ System',
description = 'Playlist ist leer!',
type = 'error'
})
return
end
currentPlaylist = playlist
currentSongIndex = 1
local firstSong = playlist.songs[1]
PlayMusic(firstSong.title, firstSong.url)
lib.notify({
title = 'DJ System',
description = 'Playlist "' .. playlist.name .. '" wird abgespielt',
type = 'success'
})
end
function ShowPlaylistSongs(playlist)
local options = {}
for i, song in pairs(playlist.songs) do
local songType = IsValidYouTubeUrl(song.url) and "YouTube" or "Direkt"
table.insert(options, {
title = song.title,
description = 'Typ: ' .. songType .. ' | Klicken zum Abspielen',
icon = IsValidYouTubeUrl(song.url) and 'fab fa-youtube' or 'music',
onSelect = function()
PlayMusic(song.title, song.url)
end
})
end
if #options == 0 then
table.insert(options, {
title = 'Keine Songs',
description = 'Diese Playlist ist leer',
icon = 'exclamation'
})
end
lib.registerContext({
id = 'playlist_songs',
title = playlist.name .. ' - Songs',
menu = 'playlist_options',
options = options
})
lib.showContext('playlist_songs')
end
function DeletePlaylist(playlist)
local confirm = lib.alertDialog({
header = 'Playlist löschen',
content = 'Möchtest du die Playlist "' .. playlist.name .. '" wirklich löschen?',
centered = true,
cancel = true
})
if confirm == 'confirm' then
TriggerServerEvent('dj:server:deletePlaylist', playlist.id)
end
end
-- Server Events
RegisterNetEvent('dj:client:playMusic', function(data)
SendNUIMessage({
type = 'playMusic',
url = data.url,
volume = data.volume,
title = data.title
})
lib.notify({
title = 'DJ System',
description = 'Spielt ab: ' .. data.title,
type = 'success'
})
end)
RegisterNetEvent('dj:client:stopMusic', function()
SendNUIMessage({
type = 'stopMusic'
})
end)
RegisterNetEvent('dj:client:setVolume', function(volume)
SendNUIMessage({
type = 'setVolume',
volume = volume
})
end)
RegisterNetEvent('dj:client:updatePlaylists', function(data)
playlists = data
end)
RegisterNetEvent('dj:client:notify', function(message, type)
lib.notify({
title = 'DJ System',
description = message,
type = type or 'info'
})
end)
-- Music Range Check
CreateThread(function()
while true do
Wait(1000)
if isPlaying and currentDJBooth then
local playerCoords = GetEntityCoords(PlayerPedId())
local distance = #(playerCoords - currentDJBooth.coords)
local range = CalculateRange()
if distance > range then
SendNUIMessage({
type = 'fadeOut'
})
else
SendNUIMessage({
type = 'fadeIn'
})
end
end
end
end)
-- Song End Handler
RegisterNUICallback('songEnded', function(data, cb)
if currentPlaylist and currentSongIndex < #currentPlaylist.songs then
-- Nächster Song in Playlist
currentSongIndex = currentSongIndex + 1
local nextSong = currentPlaylist.songs[currentSongIndex]
PlayMusic(nextSong.title, nextSong.url)
else
-- Playlist beendet
isPlaying = false
currentSong = nil
currentPlaylist = nil
currentSongIndex = 1
end
cb('ok')
end)
-- Audio Error Handler
RegisterNUICallback('audioError', function(data, cb)
lib.notify({
title = 'DJ System',
description = 'Audio Fehler: ' .. (data.error or 'Unbekannter Fehler'),
type = 'error'
})
-- Reset playing state
isPlaying = false
currentSong = nil
cb('ok')
end)
-- Song Progress (optional)
RegisterNUICallback('songProgress', function(data, cb)
-- Du kannst hier Song-Progress verarbeiten
-- z.B. für eine Progress-Bar im Menü
cb('ok')
end)