diff --git a/VERSION b/VERSION index 4684374..872765e 100644 --- a/VERSION +++ b/VERSION @@ -1 +1 @@ -1.8 \ No newline at end of file +1.9 \ No newline at end of file diff --git a/client/client.lua b/client/client.lua index 89af63e..009b3db 100644 --- a/client/client.lua +++ b/client/client.lua @@ -1,6 +1,6 @@ MSK = {} -local callbackRequest = {} +local callbackRequest, Callbacks = {}, {} if Config.Framework:match('esx') then ESX = exports["es_extended"]:getSharedObject() @@ -8,12 +8,31 @@ elseif Config.Framework:match('qbcore') then QBCore = exports['qb-core']:GetCoreObject() end +MSK.RegisterCallback = function(name, cb) + Callbacks[name] = cb +end + +MSK.TriggerCallback = function(name, ...) + local requestId = GenerateRequestKey(callbackRequest) + local response + + callbackRequest[requestId] = function(...) + response = {...} + end + + TriggerServerEvent('msk_core:triggerCallback', name, requestId, ...) + + while not response do Wait(0) end + + return table.unpack(response) +end + MSK.Notification = function(title, message, info, time) if Config.Notification == 'native' then SetNotificationTextEntry('STRING') AddTextComponentString(message) DrawNotification(false, true) - else + elseif Config.Notification == 'nui' or Config.Notification == 'msk' then SendNUIMessage({ action = 'notify', title = title, @@ -21,6 +40,8 @@ MSK.Notification = function(title, message, info, time) info = info or 'general', time = time or 5000 }) + elseif Config.Notification == 'okok' then + exports['okokNotify']:Alert(title, message, time or 5000, info or 'info') end end @@ -65,23 +86,6 @@ MSK.Draw3DText = function(coords, text, size, font) ClearDrawOrigin() end -MSK.TriggerCallback = function(name, ...) - local requestId = GenerateRequestKey(callbackRequest) - local response - - callbackRequest[requestId] = function(...) - response = {...} - end - - TriggerServerEvent('msk_core:triggerCallback', name, requestId, ...) - - while not response do - Wait(0) - end - - return table.unpack(response) -end - MSK.HasItem = function(item) if not Config.Framework:match('esx') or Config.Framework:match('qbcore') then logging('error', ('Function %s can not used without Framework!'):format('MSK.HasItem')) @@ -116,8 +120,19 @@ MSK.IsVehicleEmpty = function(vehicle) return passengers == 0 and driverSeatFree end +MSK.GetPedMugshot = function(ped, transparent) + if not DoesEntityExist(ped) then return end + local mugshot = transparent and RegisterPedheadshotTransparent(ped) or RegisterPedheadshot(ped) + + while not IsPedheadshotReady(mugshot) do + Wait(0) + end + + return mugshot, GetPedheadshotTxdString(mugshot) +end + GenerateRequestKey = function(tbl) - local id = string.upper(MSK.GetRandomLetter(3)) .. math.random(000, 999) .. string.upper(MSK.GetRandomLetter(2)) .. math.random(00, 99) + local id = string.upper(MSK.GetRandomString(3)) .. math.random(000, 999) .. string.upper(MSK.GetRandomString(2)) .. math.random(00, 99) if not tbl[id] then return tostring(id) @@ -134,6 +149,15 @@ AddEventHandler("msk_core:responseCallback", function(requestId, ...) end end) +RegisterNetEvent('msk_core:triggerCallback') +AddEventHandler('msk_core:triggerCallback', function(name, requestId, ...) + if Callbacks[name] then + Callbacks[name](GetPlayerServerId(PlayerId()), function(...) + TriggerServerEvent("msk_core:responseCallback", requestId, ...) + end, ...) + end +end) + RegisterNetEvent("msk_core:notification") AddEventHandler("msk_core:notification", function(title, message, info, time) MSK.Notification(title, message, info, time) diff --git a/client/client_progress.lua b/client/client_progress.lua new file mode 100644 index 0000000..2f8db3c --- /dev/null +++ b/client/client_progress.lua @@ -0,0 +1,18 @@ +progressStart = function(text, time, color) + SendNUIMessage({ + action = 'progressBarStart', + text = text, + time = time, + color = color or '#5eb131', + }) +end +MSK.ProgressBar = progressStart +exports('ProgressBar', progressStart) + +progressStop = function() + SendNUIMessage({ + action = 'progressBarStop', + }) +end +MSK.ProgressStop = progressStop +exports('ProgressStop', progressStop) \ No newline at end of file diff --git a/common/common.lua b/common/common.lua index e5431b6..bf3ace9 100644 --- a/common/common.lua +++ b/common/common.lua @@ -128,7 +128,18 @@ MSK.logging = function(code, ...) end end +exports('getConfig', function() + return Config +end) + logging = function(code, ...) if not Config.Debug then return end - MSK.logging(code, ...) + + if code == 'error' then + print("[^2msk_core^0]", '[^1ERROR^0]', ...) + elseif code == 'debug' then + print("[^2msk_core^0]", '[^3DEBUG^0]', ...) + elseif code == 'info' then + print("[^2msk_core^0]", '[^4Info^0]', ...) + end end \ No newline at end of file diff --git a/config.lua b/config.lua index f87d2d7..18eb90a 100644 --- a/config.lua +++ b/config.lua @@ -13,5 +13,6 @@ Config.showCoords = { } ---------------------------------------------------------------- -- Set to 'native' for FiveM Native Notification --- Set to 'nui' for NUI Notification -Config.Notification = 'nui' \ No newline at end of file +-- Set to 'msk' for NUI Notification +-- Set to 'okok' for OKOK Notification +Config.Notification = 'msk' \ No newline at end of file diff --git a/fxmanifest.lua b/fxmanifest.lua index e683ebf..2f043e1 100644 --- a/fxmanifest.lua +++ b/fxmanifest.lua @@ -4,7 +4,7 @@ games { 'gta5' } author 'Musiker15 - MSK Scripts' name 'msk_core' description 'Core functions for MSK Scripts' -version '1.8' +version '1.9' lua54 'yes' diff --git a/html/script.js b/html/script.js index fc92ab0..e238787 100644 --- a/html/script.js +++ b/html/script.js @@ -21,6 +21,10 @@ window.addEventListener('message', (event) => { document.getElementById(input).placeholder = data.placeholder; $(".msk-input-container").fadeIn() $("#msk-input-title").text(data.header) + } else if (event.data.action == 'progressBarStart') { + progressBarStart(event.data); + } else if (event.data.action == 'progressBarStop') { + progressBarStop(event.data.id); } }) @@ -104,22 +108,69 @@ notification = (title, message, info, time) => { /* MSK Input */ -function closeInputUI(send) { +closeInputUI = (send) => { $(".msk-input-container").fadeOut() if (!send) { $.post(`http://${GetParentResourceName()}/closeInput`, JSON.stringify({})) } } -document.onkeyup = function(data) { +document.onkeyup = (data) => { if (data.which == 27) { closeInputUI() } } -function input() { +$("#small-input").keydown((event) => { + if (event.keyCode == 13) { + event.preventDefault(); + } +}) + +input = () => { var textfield = '#small-input' if (field) {textfield = '#big-input'} $.post(`http://${GetParentResourceName()}/submitInput`, JSON.stringify({input: $(textfield).val()})); $(textfield).val(''); closeInputUI(true) +} + +/* MSK ProgressBar */ + +let activeBars = new Map(); // Using a Map to store active bars with their IDs as keys +let isProgressActive = false + +progressBarStart = (data) => { + if (activeBars.has(data.id)) { + $.post(`https://${GetParentResourceName()}/notif`, JSON.stringify({ text: "Already doing an action." })); + return; + } + + let progressBar = { + element: $('#progress'), + elementValue: $('#progress-value') + }; + + activeBars.set(data.id, progressBar); + + progressBar.element.removeClass('hidden'); + progressBar.elementValue.css("animation",`load ${data.time}s normal forwards`); + progressBar.element.css("animation",`glow ${data.time}s normal forwards`); + + $('#progress-text').text(data.text); + document.body.style.setProperty('--mainColor', data.color); + + setTimeout(() => { + stopProgress(data.id); + }, data.time); +} + +progressBarStop = (id) => { + let progressBar = activeBars.get(id); + + if (progressBar) { + progressBar.element.addClass('hidden'); + progressBar.elementValue.css("animation",''); + progressBar.element.css("animation",''); + activeBars.delete(id); + } } \ No newline at end of file diff --git a/html/style.css b/html/style.css index 89356ba..4f25b5f 100644 --- a/html/style.css +++ b/html/style.css @@ -51,7 +51,7 @@ /* MSK Input */ body { - overflow:hidden; + overflow: hidden; user-select: none; } @@ -61,104 +61,104 @@ textarea { ::placeholder { color: white; - opacity:0.8 - } + opacity: 0.8 +} * { --Main: radial-gradient(180vh circle at 0 -60%,#086d04,#050505); - --Input: #1fb11f59; - --Input-Border: #24b11f79; + --Input: #1fb11f59; + --Input-Border: #24b11f79; user-select: none; box-sizing: border-box; - font-family:poppins + font-family: poppins } #close { position: absolute; - width:2vh; - height:2vh; - right:1.04vh; - text-align:center; - line-height:2vh; - border-radius:0.4vh; - background:#1fb11f59; + width: 2vh; + height: 2vh; + right: 1.04vh; + text-align: center; + line-height: 2vh; + border-radius: 0.4vh; + background: #1fb11f59; transition: 400ms; } #close:hover { - background:#1fb11f; + background: #1fb11f; } .msk-input-container { - display:none; + display: none; position: absolute; - width:40vh; - height:auto; - background:radial-gradient(110vh circle at 0 -60%,#075705,#050505); - left:50%; - top:50%; + width: 40vh; + height: auto; + background: radial-gradient(110vh circle at 0 -60%,#075705,#050505); + left: 50%; + top: 50%; transform: translate(-50%, -50%); - border-radius:1.4vh; - color:white; - text-align:center; - padding-top:0.8vh; - text-transform:uppercase; + border-radius: 1.4vh; + color: white; + text-align: center; + padding-top: 0.8vh; + text-transform: uppercase; font-weight: bold; - font-size:1.4vh; - padding-bottom:1.4vh; - border:0.2vh #1fb11f solid; + font-size: 1.4vh; + padding-bottom: 1.4vh; + border: 0.2vh #1fb11f solid; } .msk-input { - width:36vh; - background:#1fb11f2c; - outline:none; - border:none; - overflow:hidden; - border:0.1vh #1fb11f solid; - border-radius:0.4vh; - color:white; - padding:0.72vh; - padding-top:0.4vh; - padding-bottom:0.2vh; + width: 36vh; + background: #1fb11f2c; + outline: none; + border: none; + overflow: hidden; + border: 0.1vh #1fb11f solid; + border-radius: 0.4vh; + color: white; + padding: 0.72vh; + padding-top: 0.4vh; + padding-bottom: 0.2vh; transition: 400ms; } .msk-input:hover { - border-color:#00ff00 + border-color: #00ff00 } #big-input { - display:none; - margin-top:1.2vh; - height:10vh; + display: none; + margin-top: 1.2vh; + height: 10vh; } #small-input { - display:all; - margin-top:1.4vh; + display: all; + margin-top: 1.4vh; white-space: nowrap; } .msk-submit-button { position: relative; - width:16vh; - height:3.2vh; - right:-10vh; - top:0.4vh; - background:#1fb11f2c; - border:0.1vh #1fb11f solid; - border-radius:0.4vh; - font-weight:bold; - font-size:1.4vh; + width: 16vh; + height: 3.2vh; + right: -10vh; + top: 0.4vh; + background: #1fb11f2c; + border: 0.1vh #1fb11f solid; + border-radius: 0.4vh; + font-weight: bold; + font-size: 1.4vh; text-transform: uppercase; - color:white; + color: white; transition: 400ms; } .msk-submit-button:hover { - background:#1fb11f; - letter-spacing:0.2vh; + background: #1fb11f; + letter-spacing: 0.2vh; } \ No newline at end of file diff --git a/server/server.lua b/server/server.lua index c80ea57..b814b64 100644 --- a/server/server.lua +++ b/server/server.lua @@ -1,6 +1,6 @@ MSK = {} -local RegisteredCommands, Callbacks = {}, {} +local RegisteredCommands, Callbacks, callbackRequest = {}, {}, {} AddEventHandler('onResourceStart', function(resource) if GetCurrentResourceName() ~= 'msk_core' then @@ -16,6 +16,25 @@ elseif Config.Framework:match('qbcore') then QBCore = exports['qb-core']:GetCoreObject() end +MSK.RegisterCallback = function(name, cb) + Callbacks[name] = cb +end + +MSK.TriggerCallback = function(name, playerId, ...) + local requestId = GenerateRequestKey(callbackRequest) + local response + + callbackRequest[requestId] = function(...) + response = {...} + end + + TriggerClientEvent('msk_core:triggerCallback', playerId, name, requestId, ...) + + while not response do Wait(0) end + + return table.unpack(response) +end + MSK.RegisterCommand = function(name, group, cb, console, framework, suggestion) if type(name) == 'table' then for k, v in ipairs(name) do @@ -155,10 +174,6 @@ MSK.AddWebhook = function(webhook, botColor, botName, botAvatar, title, descript }) end -MSK.RegisterCallback = function(name, cb) - Callbacks[name] = cb -end - MSK.HasItem = function(xPlayer, item) if not xPlayer then logging('error', 'Player on Function MSK.HasItem does not exist!') return end if not Config.Framework:match('esx') or Config.Framework:match('qbcore') then @@ -201,6 +216,24 @@ AddEventHandler('msk_core:triggerCallback', function(name, requestId, ...) end end) +RegisterNetEvent("msk_core:responseCallback") +AddEventHandler("msk_core:responseCallback", function(requestId, ...) + if callbackRequest[requestId] then + callbackRequest[requestId](...) + callbackRequest[requestId] = nil + end +end) + +GenerateRequestKey = function(tbl) + local id = string.upper(MSK.GetRandomString(3)) .. math.random(000, 999) .. string.upper(MSK.GetRandomString(2)) .. math.random(00, 99) + + if not tbl[id] then + return tostring(id) + else + GenerateRequestKey(tbl) + end +end + doesPlayerIdExist = function(playerId) for k, id in pairs(GetPlayers()) do if id == playerId then diff --git a/server/server_player.lua b/server/server_player.lua new file mode 100644 index 0000000..5bd8a1e --- /dev/null +++ b/server/server_player.lua @@ -0,0 +1,70 @@ +MSK.GetPlayer = function(player) + local Player + + if player.source then + if Config.Framework == 'esx' then + Player = ESX.GetPlayerFromId(player.source) + elseif Config.Framework == 'qbcore' then + Player = QBCore.Functions.GetPlayer(player.source) + end + elseif player.identifier then + if Config.Framework == 'esx' then + Player = ESX.GetPlayerFromIdentifier(player.identifier) + elseif Config.Framework == 'qbcore' then + Player = MSK.GetPlayer({source = QBCore.Functions.GetSource(player.identifier)}) + end + elseif player.citizenid then + if Config.Framework == 'esx' then + Player = ESX.GetPlayerFromIdentifier(player.citizenid) + elseif Config.Framework == 'qbcore' then + Player = QBCore.Functions.GetPlayerByCitizenId(player.citizenid) + end + elseif player.phone then + if Config.Framework == 'esx' then + if ESX.GetPlayerFromPhoneNumber then + Player = ESX.GetPlayerFromPhoneNumber(player.phone) + else + local data = MySQL.query.await('SELECT * from users WHERE phone_number = ?', {player.phone}) + if data and data[1] then Player = ESX.GetPlayerFromIdentifier(data[1].identifier) end + end + elseif Config.Framework == 'qbcore' then + Player = QBCore.Functions.GetPlayerByPhone(tostring(player.phone)) + end + end + + return Player +end + +MSK.GetPlayers = function(key, val) + local Players + + if Config.Framework == 'esx' then + Players = ESX.GetExtendedPlayers(key, val) + elseif Config.Framework == 'qbcore' then + if not key then + Players = QBCore.Functions.GetQBPlayers() + else + local qbPlayers + + for k, Player in pairs(QBCore.Functions.GetQBPlayers()) do + if key == 'job' then + if Player.PlayerData.job.name == val then + qbPlayers[#qbPlayers + 1] = Player + end + elseif key == 'gang' then + if Player.PlayerData.gang.name == val then + qbPlayers[#qbPlayers + 1] = Player + end + elseif key == 'group' then + if IsPlayerAceAllowed(Player.PlayerData.source, val) then + qbPlayers[#qbPlayers + 1] = Player + end + end + end + + Players = qbPlayers + end + end + + return Players +end \ No newline at end of file