forked from Simnation/Main
ed
This commit is contained in:
parent
0e29315dd1
commit
e0a3b21c61
7 changed files with 1463 additions and 0 deletions
587
resources/[tools]/nordi_dj/client/main.lua
Normal file
587
resources/[tools]/nordi_dj/client/main.lua
Normal 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)
|
Loading…
Add table
Add a link
Reference in a new issue