From 9fbab7a4e649e900f67045a0cc898430cc404b88 Mon Sep 17 00:00:00 2001 From: Zerio Date: Sat, 25 May 2024 21:04:30 +0000 Subject: [PATCH 01/26] fix: remove usable item after resource stop --- server/events.lua | 8 ++++++++ server/functions.lua | 21 ++++++++++++++++++++- 2 files changed, 28 insertions(+), 1 deletion(-) diff --git a/server/events.lua b/server/events.lua index 49ec40f..e1cfcb3 100644 --- a/server/events.lua +++ b/server/events.lua @@ -18,6 +18,14 @@ AddEventHandler('playerDropped', function(reason) QBCore.Players[src] = nil end) +AddEventHandler("onResourceStop", function(resName) + for i,v in pairs(QBCore.UsableItems) do + if v.resource == resName then + QBCore.UsableItems[i] = nil + end + end +end) + -- Player Connecting local function onPlayerConnecting(name, _, deferrals) diff --git a/server/functions.lua b/server/functions.lua index 3f7689d..116573f 100644 --- a/server/functions.lua +++ b/server/functions.lua @@ -462,7 +462,26 @@ end ---@param item string ---@param data function function QBCore.Functions.CreateUseableItem(item, data) - QBCore.UsableItems[item] = data + local rawFunc = nil + + if type(data) == "table" then + if rawget(data, '__cfx_functionReference') then + rawFunc = data + elseif data.cb and rawget(data.cb, '__cfx_functionReference') then + rawFunc = data.cb + elseif data.callback and rawget(data.callback, '__cfx_functionReference') then + rawFunc = data.callback + end + elseif type(data) == "function" then + rawFunc = data + end + + if rawFunc then + QBCore.UsableItems[item] = { + func = rawFunc, + resource = GetInvokingResource() + } + end end ---Checks if the given item is usable From d203762b73db0d8d8111c5805b8d85d387736965 Mon Sep 17 00:00:00 2001 From: Zerio Date: Sat, 25 May 2024 21:10:01 +0000 Subject: [PATCH 02/26] fix: lint issues --- client/functions.lua | 15 ++++++--------- 1 file changed, 6 insertions(+), 9 deletions(-) diff --git a/client/functions.lua b/client/functions.lua index 4b4bda1..3224b0d 100644 --- a/client/functions.lua +++ b/client/functions.lua @@ -43,16 +43,13 @@ end function QBCore.Functions.LookAtEntity(entity, timeout, speed) local involved = GetInvokingResource() if not DoesEntityExist(entity) then - turnPromise:reject(involved .. ' :^1 Entity does not exist') - return turnPromise.value + return involved .. ' :^1 Entity does not exist' end - if not type(entity) == 'number' then - turnPromise:reject(involved .. ' :^1 Entity must be a number') - return turnPromise.value + if type(entity) ~= 'number' then + return involved .. ' :^1 Entity must be a number' end - if not type(speed) == 'number' then - turnPromise:reject(involved .. ' :^1 Speed must be a number') - return turnPromise.value + if type(speed) ~= 'number' then + return involved .. ' :^1 Speed must be a number' end if speed > 5.0 then speed = 5.0 end if timeout > 5000 then timeout = 5000 end @@ -62,7 +59,7 @@ function QBCore.Functions.LookAtEntity(entity, timeout, speed) local dx = targetPos.x - playerPos.x local dy = targetPos.y - playerPos.y local targetHeading = GetHeadingFromVector_2d(dx, dy) - local turnSpeed = speed + local turnSpeed = nil local startTimeout = GetGameTimer() while true do local currentHeading = GetEntityHeading(ped) From 36549a6cc92b11fea919671a0b2f38d9f8a42508 Mon Sep 17 00:00:00 2001 From: Zerio Date: Sat, 25 May 2024 21:14:44 +0000 Subject: [PATCH 03/26] fix: `value assigned to variable 'turnSpeed' is unused` --- client/functions.lua | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/client/functions.lua b/client/functions.lua index 3224b0d..5530d82 100644 --- a/client/functions.lua +++ b/client/functions.lua @@ -59,7 +59,7 @@ function QBCore.Functions.LookAtEntity(entity, timeout, speed) local dx = targetPos.x - playerPos.x local dy = targetPos.y - playerPos.y local targetHeading = GetHeadingFromVector_2d(dx, dy) - local turnSpeed = nil + local turnSpeed local startTimeout = GetGameTimer() while true do local currentHeading = GetEntityHeading(ped) From fe450d5b11157c92b226ac7b814bbae87f872aec Mon Sep 17 00:00:00 2001 From: Rojin Chhetri <68652932+RojinxChhetri@users.noreply.github.com> Date: Sat, 21 Sep 2024 15:11:59 +0000 Subject: [PATCH 04/26] added Nepali Locales --- locale/np.lua | 133 ++++++++++++++++++++++++++++++++++++++++++++++++++ 1 file changed, 133 insertions(+) create mode 100644 locale/np.lua diff --git a/locale/np.lua b/locale/np.lua new file mode 100644 index 0000000..ee88330 --- /dev/null +++ b/locale/np.lua @@ -0,0 +1,133 @@ +local Translations = { + error = { + not_online = 'खिलाडी अनलाइन छैन', + wrong_format = 'गलत ढाँचा', + missing_args = 'सबै तर्कहरू प्रविष्ट गरिएको छैन (x, y, z)', + missing_args2 = 'सबै तर्कहरू पूरा गर्नुपर्छ!', + no_access = 'यस आदेशको लागि पहुँच छैन', + company_too_poor = 'तपाईंको नियोक्ता टाट पल्टेको छ', + item_not_exist = 'वस्तु अवस्थित छैन', + too_heavy = 'इन्वेन्टरी धेरै भरिएको छ', + location_not_exist = 'स्थान अवस्थित छैन', + duplicate_license = '[QBCORE] - दोहोरिएको रकस्टार लाइसेन्स भेटियो', + no_valid_license = '[QBCORE] - मान्य रकस्टार लाइसेन्स भेटिएन', + not_whitelisted = '[QBCORE] - तपाईं यस सर्भरको लागि सेतो सूचीमा हुनुहुन्न', + server_already_open = 'सर्भर पहिले नै खुल्ला छ', + server_already_closed = 'सर्भर पहिले नै बन्द छ', + no_permission = 'तपाईंलाई यसका लागि अनुमति छैन।', + no_waypoint = 'वेपॉइंट सेट गरिएको छैन।', + tp_error = 'टेलिपोर्ट गर्दा त्रुटि।', + ban_table_not_found = '[QBCORE] - डाटाबेसमा प्रतिबन्ध तालिका फेला पार्न सकेन। कृपया तपाईंले SQL फाइल सही रूपमा आयात गरेको सुनिश्चित गर्नुहोस्।', + connecting_database_error = '[QBCORE] - डाटाबेससँग जडान गर्दा त्रुटि भयो। कृपया SQL सर्भर चलिरहेको छ र server.cfg फाइलमा विवरणहरू सही छन् भन्ने सुनिश्चित गर्नुहोस्।', + connecting_database_timeout = '[QBCORE] - डाटाबेस जडानले समय समाप्त गर्यो। कृपया SQL सर्भर चलिरहेको छ र server.cfg फाइलमा विवरणहरू सही छन् भन्ने सुनिश्चित गर्नुहोस्।', + }, + success = { + server_opened = 'सर्भर खोलियो', + server_closed = 'सर्भर बन्द भयो', + teleported_waypoint = 'वेपॉइंटमा टेलिपोर्ट भयो।', + }, + info = { + received_paycheck = 'तपाईंले $%{value} को तलब प्राप्त गर्नुभयो', + job_info = 'काम: %{value} | ग्रेड: %{value2} | ड्युटी: %{value3}', + gang_info = 'ग्याङ: %{value} | ग्रेड: %{value2}', + on_duty = 'तपाईं अब ड्युटीमा हुनुहुन्छ!', + off_duty = 'तपाईं अब ड्युटीबाट बाहिर हुनुहुन्छ!', + checking_ban = 'नमस्ते %s। हामी तपाईं प्रतिबन्धित हुनुहुन्छ कि छैन जाँच गर्दैछौं।', + join_server = 'स्वागत छ %s {Server Name} मा।', + checking_whitelisted = 'नमस्ते %s। हामी तपाईंको अनुमतिहरू जाँच्दैछौं।', + exploit_banned = 'तपाईंलाई धोकाधडीको लागि प्रतिबन्ध लगाइएको छ। थप जानकारीका लागि हाम्रो डिस्कर्ड हेर्नुहोस्: %{discord}', + exploit_dropped = 'धोकाधडीको लागि तपाईंलाई निकालिएको छ', + }, + command = { + tp = { + help = 'खिलाडी वा निर्देशांकमा टेलिपोर्ट गर्नुहोस् (केवल प्रशासक)', + params = { + x = { name = 'id/x', help = 'खिलाडीको ID वा X स्थिति' }, + y = { name = 'y', help = 'Y स्थिति' }, + z = { name = 'z', help = 'Z स्थिति' }, + }, + }, + tpm = { help = 'मार्करमा टेलिपोर्ट गर्नुहोस् (केवल प्रशासक)' }, + togglepvp = { help = 'सर्भरमा PVP सक्रिय/निष्क्रिय गर्नुहोस् (केवल प्रशासक)' }, + addpermission = { + help = 'खिलाडीलाई अनुमति दिनुहोस् (केवल देवता)', + params = { + id = { name = 'id', help = 'खिलाडीको ID' }, + permission = { name = 'permission', help = 'अनुमतिका स्तर' }, + }, + }, + removepermission = { + help = 'खिलाडीबाट अनुमति हटाउनुहोस् (केवल देवता)', + params = { + id = { name = 'id', help = 'खिलाडीको ID' }, + permission = { name = 'permission', help = 'अनुमतिका स्तर' }, + }, + }, + openserver = { help = 'सबैलाई सर्भर खोल्नुहोस् (केवल प्रशासक)' }, + closeserver = { + help = 'अनुमति बिना मानिसहरूलाई सर्भर बन्द गर्नुहोस् (केवल प्रशासक)', + params = { + reason = { name = 'reason', help = 'बन्द गर्ने कारण (वैकल्पिक)' }, + }, + }, + car = { + help = 'सवारी साधन उत्पन्न गर्नुहोस् (केवल प्रशासक)', + params = { + model = { name = 'model', help = 'सवारी साधनको मोडल नाम' }, + }, + }, + dv = { help = 'सवारी साधन मेटाउनुहोस् (केवल प्रशासक)' }, + dvall = { help = 'सबै सवारी साधन मेटाउनुहोस् (केवल प्रशासक)' }, + dvp = { help = 'सबै NPC मेटाउनुहोस् (केवल प्रशासक)' }, + dvo = { help = 'सबै वस्तुहरू मेटाउनुहोस् (केवल प्रशासक)' }, + givemoney = { + help = 'खिलाडीलाई पैसा दिनुहोस् (केवल प्रशासक)', + params = { + id = { name = 'id', help = 'खिलाडीको ID' }, + moneytype = { name = 'moneytype', help = 'पैसाको प्रकार (नगद, बैंक, क्रिप्टो)' }, + amount = { name = 'amount', help = 'पैसाको रकम' }, + }, + }, + setmoney = { + help = 'खिलाडीको पैसा सेट गर्नुहोस् (केवल प्रशासक)', + params = { + id = { name = 'id', help = 'खिलाडीको ID' }, + moneytype = { name = 'moneytype', help = 'पैसाको प्रकार (नगद, बैंक, क्रिप्टो)' }, + amount = { name = 'amount', help = 'पैसाको रकम' }, + }, + }, + job = { help = 'तपाईंको काम जाँच्नुहोस्' }, + setjob = { + help = 'खिलाडीलाई काम दिनुहोस् (केवल प्रशासक)', + params = { + id = { name = 'id', help = 'खिलाडीको ID' }, + job = { name = 'job', help = 'कामको नाम' }, + grade = { name = 'grade', help = 'कामको स्तर' }, + }, + }, + gang = { help = 'तपाईंको ग्याङ जाँच्नुहोस्' }, + setgang = { + help = 'खिलाडीलाई ग्याङ दिनुहोस् (केवल प्रशासक)', + params = { + id = { name = 'id', help = 'खिलाडीको ID' }, + gang = { name = 'gang', help = 'ग्याङको नाम' }, + grade = { name = 'grade', help = 'ग्याङको स्तर' }, + }, + }, + ooc = { help = 'OOC च्याट सन्देश' }, + me = { + help = 'स्थानीय सन्देश देखाउनुहोस्', + params = { + message = { name = 'message', help = 'पठाउनको लागि सन्देश' } + }, + }, + }, +} + +if GetConvar('qb_locale', 'en') == 'np' then + Lang = Locale:new({ + phrases = Translations, + warnOnMissing = true, + fallbackLang = Locale:new({ phrases = {}, warnOnMissing = true }) -- Fallback to empty locale if needed + }) +end From 36ce1524fbf1765971fe33db4b81c6bd3fd20313 Mon Sep 17 00:00:00 2001 From: Mustache Dom <123716453+Mustachedom@users.noreply.github.com> Date: Tue, 22 Oct 2024 15:03:03 -0700 Subject: [PATCH 05/26] added config option to limit negative amount No Config option and since bank isn't listed in QBConfig.Money.DontAllowMinus then **any** script that has ``` if Player.Functions.RemoveMoney('bank'. Value) then ``` will allot them to go 11 characters negative causing massive exploits --- config.lua | 1 + 1 file changed, 1 insertion(+) diff --git a/config.lua b/config.lua index f0dbf8d..69a4c85 100644 --- a/config.lua +++ b/config.lua @@ -8,6 +8,7 @@ QBConfig.StatusInterval = 5000 -- how often to check hu QBConfig.Money = {} QBConfig.Money.MoneyTypes = { cash = 500, bank = 5000, crypto = 0 } -- type = startamount - Add or remove money types for your server (for ex. blackmoney = 0), remember once added it will not be removed from the database! QBConfig.Money.DontAllowMinus = { 'cash', 'crypto' } -- Money that is not allowed going in minus +QBConfig.Money.MinusLimit = 5000 -- The maximum amount you can be negative QBConfig.Money.PayCheckTimeOut = 10 -- The time in minutes that it will give the paycheck QBConfig.Money.PayCheckSociety = false -- If true paycheck will come from the society account that the player is employed at, requires qb-management From 06f7f6e96764155714ca68b6edcbc3afb370e009 Mon Sep 17 00:00:00 2001 From: Mustache Dom <123716453+Mustachedom@users.noreply.github.com> Date: Tue, 22 Oct 2024 15:06:17 -0700 Subject: [PATCH 06/26] Update config.lua --- config.lua | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/config.lua b/config.lua index 69a4c85..3c77309 100644 --- a/config.lua +++ b/config.lua @@ -8,7 +8,7 @@ QBConfig.StatusInterval = 5000 -- how often to check hu QBConfig.Money = {} QBConfig.Money.MoneyTypes = { cash = 500, bank = 5000, crypto = 0 } -- type = startamount - Add or remove money types for your server (for ex. blackmoney = 0), remember once added it will not be removed from the database! QBConfig.Money.DontAllowMinus = { 'cash', 'crypto' } -- Money that is not allowed going in minus -QBConfig.Money.MinusLimit = 5000 -- The maximum amount you can be negative +QBConfig.Money.MinusLimit = -5000 -- The maximum amount you can be negative QBConfig.Money.PayCheckTimeOut = 10 -- The time in minutes that it will give the paycheck QBConfig.Money.PayCheckSociety = false -- If true paycheck will come from the society account that the player is employed at, requires qb-management From 080556c4256d8766d7586cd4fa0fd5f3bffad6d5 Mon Sep 17 00:00:00 2001 From: Mustache Dom <123716453+Mustachedom@users.noreply.github.com> Date: Tue, 22 Oct 2024 15:07:23 -0700 Subject: [PATCH 07/26] checks to see if RemoveMoney has enough removes exploit to allow bank to be -99999999999 --- server/player.lua | 1 + 1 file changed, 1 insertion(+) diff --git a/server/player.lua b/server/player.lua index 7b3363f..d446cf3 100644 --- a/server/player.lua +++ b/server/player.lua @@ -341,6 +341,7 @@ function QBCore.Player.CreatePlayer(PlayerData, Offline) end end end + if self.PlayerData.money[moneytype] - amount <= QBConfig.Money.MinusLimit then return false end self.PlayerData.money[moneytype] = self.PlayerData.money[moneytype] - amount if not self.Offline then From 1ce5dd831bf1b3c44db0f17eecb6bd915b6c4a52 Mon Sep 17 00:00:00 2001 From: Mustache Dom <123716453+Mustachedom@users.noreply.github.com> Date: Thu, 7 Nov 2024 20:22:12 -0800 Subject: [PATCH 08/26] Update player.lua --- server/player.lua | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/server/player.lua b/server/player.lua index d446cf3..dbf91b2 100644 --- a/server/player.lua +++ b/server/player.lua @@ -341,7 +341,7 @@ function QBCore.Player.CreatePlayer(PlayerData, Offline) end end end - if self.PlayerData.money[moneytype] - amount <= QBConfig.Money.MinusLimit then return false end + if self.PlayerData.money[moneytype] - amount < QBConfig.Money.MinusLimit then return false end self.PlayerData.money[moneytype] = self.PlayerData.money[moneytype] - amount if not self.Offline then From 304a6f42a04b3b953714c7276ad69575954f1bc6 Mon Sep 17 00:00:00 2001 From: Mustache Dom <123716453+Mustachedom@users.noreply.github.com> Date: Thu, 7 Nov 2024 20:47:22 -0800 Subject: [PATCH 09/26] Update player.lua --- server/player.lua | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/server/player.lua b/server/player.lua index dbf91b2..cbc5032 100644 --- a/server/player.lua +++ b/server/player.lua @@ -341,7 +341,7 @@ function QBCore.Player.CreatePlayer(PlayerData, Offline) end end end - if self.PlayerData.money[moneytype] - amount < QBConfig.Money.MinusLimit then return false end + if self.PlayerData.money[moneytype] - amount < QBCore.Config.Money.MinusLimit then return false end self.PlayerData.money[moneytype] = self.PlayerData.money[moneytype] - amount if not self.Offline then From afb8eab8edacc9048f07a55a8ec26d4e2b3ced3c Mon Sep 17 00:00:00 2001 From: James Date: Sun, 24 Nov 2024 20:18:16 +0700 Subject: [PATCH 10/26] fix(client/vehProps): fix leaking bug by forcing tankHealth & oilLevel to be float vals --- client/functions.lua | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/client/functions.lua b/client/functions.lua index 5530d82..45034a5 100644 --- a/client/functions.lua +++ b/client/functions.lua @@ -566,7 +566,7 @@ function QBCore.Functions.SetVehicleProperties(vehicle, props) SetVehicleEngineHealth(vehicle, props.engineHealth + 0.0) end if props.tankHealth then - SetVehiclePetrolTankHealth(vehicle, props.tankHealth) + SetVehiclePetrolTankHealth(vehicle, props.tankHealth + 0.0) end if props.fuelLevel then SetVehicleFuelLevel(vehicle, props.fuelLevel + 0.0) @@ -575,7 +575,7 @@ function QBCore.Functions.SetVehicleProperties(vehicle, props) SetVehicleDirtLevel(vehicle, props.dirtLevel + 0.0) end if props.oilLevel then - SetVehicleOilLevel(vehicle, props.oilLevel) + SetVehicleOilLevel(vehicle, props.oilLevel + 0.0) end if props.color1 then if type(props.color1) == 'number' then From 11718a5acc56b2a57b79175b4300f1423fde53c1 Mon Sep 17 00:00:00 2001 From: IRedScarface <68557923+IRedScarface@users.noreply.github.com> Date: Thu, 26 Dec 2024 07:47:37 +0300 Subject: [PATCH 11/26] Update tr.lua --- locale/tr.lua | 150 +++++++++++++++++++++++++++++++++++++++++--------- 1 file changed, 123 insertions(+), 27 deletions(-) diff --git a/locale/tr.lua b/locale/tr.lua index 9acc97e..630cc14 100644 --- a/locale/tr.lua +++ b/locale/tr.lua @@ -1,34 +1,130 @@ local Translations = { error = { - not_online = 'Oyuncu çevrimiçi değil.', - wrong_format = 'Yanlış format.', - missing_args = 'Hiçbir argüman girilmedi. (x, y, z)', - missing_args2 = 'Tüm argümanlar doldurulmalıdır.', - no_access = 'Bu komuta erişimin yok.', - company_too_poor = 'Şirketin hiç parası yok.', - item_not_exist = 'Eşya mevcut değil.', - too_heavy = 'Envanter çok dolu', - duplicate_license = 'Aynı rockstar lisansı zaten şu an sunucuda!', - no_valid_license = 'Geçerli bir rockstar lisans bulunamadı.', - not_whitelisted = 'Bu sunucuda whitelistin yok.' + not_online = 'Oyuncu çevrimdışı', + wrong_format = 'Hatalı format', + missing_args = 'Tüm argümanlar girilmedi (x, y, z)', + missing_args2 = 'Tüm argümanlar doldurulmalıdır!', + no_access = 'Bu komut için erişiminiz yok', + company_too_poor = 'İşvereniniz iflas etti', + item_not_exist = 'Eşya mevcut değil', + too_heavy = 'Envanter çok dolu', + location_not_exist = 'Konum mevcut değil', + duplicate_license = '[QBCORE] - Aynı Rockstar Lisansı Bulundu', + no_valid_license = '[QBCORE] - Geçerli Rockstar Lisansı Bulunamadı', + not_whitelisted = '[QBCORE] - Bu sunucu için beyaz listedesiniz', + server_already_open = 'Sunucu zaten açık', + server_already_closed = 'Sunucu zaten kapalı', + no_permission = 'Bu işlem için yetkiniz yok...', + no_waypoint = 'Bir işaret noktası ayarlanmamış.', + tp_error = 'Taşınırken hata oluştu.', + ban_table_not_found = '[QBCORE] - Veritabanında yasaklılar tablosu bulunamadı. Lütfen SQL dosyasının doğru şekilde yüklendiğinden emin olun.', + connecting_database_error = '[QBCORE] - Veritabanına bağlanırken hata oluştu. SQL sunucusunun çalıştığından ve server.cfg dosyasındaki bilgilerin doğru olduğundan emin olun.', + connecting_database_timeout = '[QBCORE] - Veritabanı bağlantısı zaman aşımına uğradı. SQL sunucusunun çalıştığından ve server.cfg dosyasındaki bilgilerin doğru olduğundan emin olun.', + }, + success = { + server_opened = 'Sunucu açıldı', + server_closed = 'Sunucu kapandı', + teleported_waypoint = 'İşaret noktasına taşındınız.', }, - success = {}, info = { - received_paycheck = '$%{value} tutarında bir maaş çeki aldın.', - job_info = 'İş: %{value} | Seviye: %{value2} | Görev: %{value3}', + received_paycheck = 'Maaşınızı $%{value} aldınız', + job_info = 'İş: %{value} | Seviye: %{value2} | Görevde: %{value3}', gang_info = 'Çete: %{value} | Seviye: %{value2}', - on_duty = 'Mesaiye girdin.', - off_duty = 'Mesaiden çıktın.', - checking_ban = 'Merhaba %s. Banlı mısın diye kontrol ediyoruz.', - join_server = 'Merhaba %s. {Server Name} adlı sunucumuza hoş geldin.', - checking_whitelisted = 'Merhaba %s. Whitelist\'in var mı diye kontrol ediyoruz.' - } + on_duty = 'Artık görevdeyiniz!', + off_duty = 'Artık görev dışında oldunuz!', + checking_ban = 'Merhaba %s. Yasaklı olup olmadığınızı kontrol ediyoruz.', + join_server = 'Hoşgeldiniz %s, {Sunucu Adı}\'na.', + checking_whitelisted = 'Merhaba %s. İzin durumunuzu kontrol ediyoruz.', + exploit_banned = 'Hile yaptığınız için yasaklandınız. Daha fazla bilgi için Discord\'umuza göz atın: %{discord}', + exploit_dropped = 'Hile yapmaktan dolayı sunucudan atıldınız', + }, + command = { + tp = { + help = 'Oyuncuya veya Koordinatlara TP (Sadece Admin)', + params = { + x = { name = 'id/x', help = 'Oyuncu ID\'si veya X konumu' }, + y = { name = 'y', help = 'Y konumu' }, + z = { name = 'z', help = 'Z konumu' }, + }, + }, + tpm = { help = 'İşaret noktasına TP (Sadece Admin)' }, + togglepvp = { help = 'Sunucuda PVP modunu aç/kapat (Sadece Admin)' }, + addpermission = { + help = 'Oyuncuya Yetki Ver (Tanrı Yetkisi)', + params = { + id = { name = 'id', help = 'Oyuncu ID\'si' }, + permission = { name = 'permission', help = 'Yetki seviyesi' }, + }, + }, + removepermission = { + help = 'Oyuncudan Yetki Al (Tanrı Yetkisi)', + params = { + id = { name = 'id', help = 'Oyuncu ID\'si' }, + permission = { name = 'permission', help = 'Yetki seviyesi' }, + }, + }, + openserver = { help = 'Sunucuyu herkes için aç (Sadece Admin)' }, + closeserver = { + help = 'Sunucuyu yetkisi olmayanlar için kapat (Sadece Admin)', + params = { + reason = { name = 'reason', help = 'Kapanma nedeni (isteğe bağlı)' }, + }, + }, + car = { + help = 'Araç Spawn Et (Sadece Admin)', + params = { + model = { name = 'model', help = 'Araç model adı' }, + }, + }, + dv = { help = 'Aracı Sil (Sadece Admin)' }, + dvall = { help = 'Tüm Araçları Sil (Sadece Admin)' }, + dvp = { help = 'Tüm Pedleri Sil (Sadece Admin)' }, + dvo = { help = 'Tüm Objeleri Sil (Sadece Admin)' }, + givemoney = { + help = 'Bir Oyuncuya Para Ver (Sadece Admin)', + params = { + id = { name = 'id', help = 'Oyuncu ID\'si' }, + moneytype = { name = 'moneytype', help = 'Para türü (nakit, banka, kripto)' }, + amount = { name = 'amount', help = 'Verilecek para miktarı' }, + }, + }, + setmoney = { + help = 'Oyuncunun Para Miktarını Ayarla (Sadece Admin)', + params = { + id = { name = 'id', help = 'Oyuncu ID\'si' }, + moneytype = { name = 'moneytype', help = 'Para türü (nakit, banka, kripto)' }, + amount = { name = 'amount', help = 'Para miktarı' }, + }, + }, + job = { help = 'İşinizi Kontrol Edin' }, + setjob = { + help = 'Bir Oyuncunun İşini Ayarla (Sadece Admin)', + params = { + id = { name = 'id', help = 'Oyuncu ID\'si' }, + job = { name = 'job', help = 'İş adı' }, + grade = { name = 'grade', help = 'İş seviyesi' }, + }, + }, + gang = { help = 'Çetenizi Kontrol Edin' }, + setgang = { + help = 'Bir Oyuncunun Çetesini Ayarla (Sadece Admin)', + params = { + id = { name = 'id', help = 'Oyuncu ID\'si' }, + gang = { name = 'gang', help = 'Çete adı' }, + grade = { name = 'grade', help = 'Çete seviyesi' }, + }, + }, + ooc = { help = 'OOC Sohbet Mesajı' }, + me = { + help = 'Yerel mesaj gönder', + params = { + message = { name = 'message', help = 'Gönderilecek mesaj' } + }, + }, + }, } -if GetConvar('qb_locale', 'en') == 'tr' then - Lang = Locale:new({ - phrases = Translations, - warnOnMissing = true, - fallbackLang = Lang, - }) -end +Lang = Lang or Locale:new({ + phrases = Translations, + warnOnMissing = true +}) From cccb4d05769daa2ae4348dad85df7cef8befdb51 Mon Sep 17 00:00:00 2001 From: IRedScarface <68557923+IRedScarface@users.noreply.github.com> Date: Thu, 26 Dec 2024 07:53:45 +0300 Subject: [PATCH 12/26] Update tr.lua --- locale/tr.lua | 11 +++++++---- 1 file changed, 7 insertions(+), 4 deletions(-) diff --git a/locale/tr.lua b/locale/tr.lua index 630cc14..d123721 100644 --- a/locale/tr.lua +++ b/locale/tr.lua @@ -124,7 +124,10 @@ local Translations = { }, } -Lang = Lang or Locale:new({ - phrases = Translations, - warnOnMissing = true -}) +if GetConvar('qb_locale', 'en') == 'tr' then + Lang = Locale:new({ + phrases = Translations, + warnOnMissing = true, + fallbackLang = Lang, + }) +end From 403d1c8c56afb65e304bb9db98b5239d2ddc1083 Mon Sep 17 00:00:00 2001 From: Psycho66626 Date: Thu, 26 Dec 2024 23:42:00 +0200 Subject: [PATCH 13/26] items.lua --- shared/items.lua | 12 ++++++------ 1 file changed, 6 insertions(+), 6 deletions(-) diff --git a/shared/items.lua b/shared/items.lua index b6f93a8..84de923 100644 --- a/shared/items.lua +++ b/shared/items.lua @@ -50,13 +50,13 @@ QBShared.Items = { weapon_pistolxm3 = { name = 'weapon_pistolxm3', label = 'Pistol XM3', weight = 1000, type = 'weapon', ammotype = 'AMMO_PISTOL', image = 'weapon_pistolxm3.png', unique = true, useable = true, description = 'Pistol XM3' }, -- Submachine Guns - weapon_microsmg = { name = 'weapon_microsmg', label = 'Micro SMG', weight = 1000, type = 'weapon', ammotype = 'AMMO_SMG', image = 'weapon_microsmg.png', unique = true, useable = false, description = 'A handheld light weight machine gun' }, - weapon_smg = { name = 'weapon_smg', label = 'SMG', weight = 1000, type = 'weapon', ammotype = 'AMMO_SMG', image = 'weapon_smg.png', unique = true, useable = false, description = 'A handheld light weight machine gun' }, + weapon_microsmg = { name = 'weapon_microsmg', label = 'Micro SMG', weight = 1000, type = 'weapon', ammotype = 'AMMO_SMG', image = 'weapon_microsmg.png', unique = true, useable = false, description = 'A handheld light weight machine gun' }, + weapon_smg = { name = 'weapon_smg', label = 'SMG', weight = 1000, type = 'weapon', ammotype = 'AMMO_SMG', image = 'weapon_smg.png', unique = true, useable = false, description = 'A handheld light weight machine gun' }, weapon_smg_mk2 = { name = 'weapon_smg_mk2', label = 'SMG Mk II', weight = 1000, type = 'weapon', ammotype = 'AMMO_SMG', image = 'weapon_smg_mk2.png', unique = true, useable = true, description = 'SMG MK2' }, - weapon_assaultsmg = { name = 'weapon_assaultsmg', label = 'Assault SMG', weight = 1000, type = 'weapon', ammotype = 'AMMO_SMG', image = 'weapon_assaultsmg.png', unique = true, useable = false, description = 'An assault version of a handheld light weight machine gun' }, - weapon_combatpdw = { name = 'weapon_combatpdw', label = 'Combat PDW', weight = 1000, type = 'weapon', ammotype = 'AMMO_SMG', image = 'weapon_combatpdw.png', unique = true, useable = false, description = 'A combat version of a handheld light weight machine gun' }, + weapon_assaultsmg = { name = 'weapon_assaultsmg', label = 'Assault SMG', weight = 1000, type = 'weapon', ammotype = 'AMMO_SMG', image = 'weapon_assaultsmg.png', unique = true, useable = false, description = 'An assault version of a handheld light weight machine gun' }, + weapon_combatpdw = { name = 'weapon_combatpdw', label = 'Combat PDW', weight = 1000, type = 'weapon', ammotype = 'AMMO_SMG', image = 'weapon_combatpdw.png', unique = true, useable = false, description = 'A combat version of a handheld light weight machine gun' }, weapon_machinepistol = { name = 'weapon_machinepistol', label = 'Tec-9', weight = 1000, type = 'weapon', ammotype = 'AMMO_PISTOL', image = 'weapon_machinepistol.png', unique = true, useable = false, description = 'A self-loading pistol capable of burst or fully automatic fire' }, - weapon_minismg = { name = 'weapon_minismg', label = 'Mini SMG', weight = 1000, type = 'weapon', ammotype = 'AMMO_SMG', image = 'weapon_minismg.png', unique = true, useable = false, description = 'A mini handheld light weight machine gun' }, + weapon_minismg = { name = 'weapon_minismg', label = 'Mini SMG', weight = 1000, type = 'weapon', ammotype = 'AMMO_SMG', image = 'weapon_minismg.png', unique = true, useable = false, description = 'A mini handheld light weight machine gun' }, weapon_raycarbine = { name = 'weapon_raycarbine', label = 'Unholy Hellbringer', weight = 1000, type = 'weapon', ammotype = 'AMMO_SMG', image = 'weapon_raycarbine.png', unique = true, useable = true, description = 'Weapon Raycarbine' }, -- Shotguns @@ -74,7 +74,7 @@ QBShared.Items = { -- Assault Rifles weapon_assaultrifle = { name = 'weapon_assaultrifle', label = 'Assault Rifle', weight = 1000, type = 'weapon', ammotype = 'AMMO_RIFLE', image = 'weapon_assaultrifle.png', unique = true, useable = false, description = 'A rapid-fire, magazine-fed automatic rifle designed for infantry use' }, weapon_assaultrifle_mk2 = { name = 'weapon_assaultrifle_mk2', label = 'Assault Rifle Mk II', weight = 1000, type = 'weapon', ammotype = 'AMMO_RIFLE', image = 'weapon_assaultrifle_mk2.png', unique = true, useable = true, description = 'Assault Rifle MK2' }, - weapon_carbinerifle = { name = 'weapon_carbinerifle', label = 'Carbine Rifle', weight = 1000, type = 'weapon', ammotype = 'AMMO_RIFLE', image = 'weapon_carbinerifle.png', unique = true, useable = false, description = 'A light weight automatic rifle' }, + weapon_carbinerifle = { name = 'weapon_carbinerifle', label = 'Carbine Rifle', weight = 1000, type = 'weapon', ammotype = 'AMMO_RIFLE', image = 'weapon_carbinerifle.png', unique = true, useable = false, description = 'A light weight automatic rifle' }, weapon_carbinerifle_mk2 = { name = 'weapon_carbinerifle_mk2', label = 'Carbine Rifle Mk II', weight = 1000, type = 'weapon', ammotype = 'AMMO_RIFLE', image = 'weapon_carbinerifle_mk2.png', unique = true, useable = true, description = 'Carbine Rifle MK2' }, weapon_advancedrifle = { name = 'weapon_advancedrifle', label = 'Advanced Rifle', weight = 1000, type = 'weapon', ammotype = 'AMMO_RIFLE', image = 'weapon_advancedrifle.png', unique = true, useable = false, description = 'An assault version of a rapid-fire, magazine-fed automatic rifle designed for infantry use' }, weapon_specialcarbine = { name = 'weapon_specialcarbine', label = 'Special Carbine', weight = 1000, type = 'weapon', ammotype = 'AMMO_RIFLE', image = 'weapon_specialcarbine.png', unique = true, useable = false, description = 'An extremely versatile assault rifle for any combat situation' }, From c1e940240d5f305369b37e96678894dacf5bdf13 Mon Sep 17 00:00:00 2001 From: Kakarot <57848836+GhzGarage@users.noreply.github.com> Date: Fri, 3 Jan 2025 16:47:19 -0600 Subject: [PATCH 14/26] Enable vehicle searching by hash allows retrieving the shared vehicle data via the hash code in addition to the model/spawn name --- shared/vehicles.lua | 5 ++++- 1 file changed, 4 insertions(+), 1 deletion(-) diff --git a/shared/vehicles.lua b/shared/vehicles.lua index bf6bf87..b745c09 100644 --- a/shared/vehicles.lua +++ b/shared/vehicles.lua @@ -765,7 +765,9 @@ local Vehicles = { { model = 'formula', name = 'PR4', brand = 'Progen', price = 100000, category = 'openwheel', type = 'automobile', shop = 'none' }, } +QBShared.VehicleHashes = QBShared.VehicleHashes or {} for i = 1, #Vehicles do + local hash = joaat(Vehicles[i].model) QBShared.Vehicles[Vehicles[i].model] = { spawncode = Vehicles[i].model, name = Vehicles[i].name, @@ -773,8 +775,9 @@ for i = 1, #Vehicles do model = Vehicles[i].model, price = Vehicles[i].price, category = Vehicles[i].category, - hash = joaat(Vehicles[i].model), + hash = hash, type = Vehicles[i].type, shop = Vehicles[i].shop } + QBShared.VehicleHashes[hash] = QBShared.Vehicles[Vehicles[i].model] end From dc8fbf04e9db19dbf44eeb4321836d2012a68c2a Mon Sep 17 00:00:00 2001 From: Zerio Date: Mon, 6 Jan 2025 21:31:23 +0100 Subject: [PATCH 15/26] feat: use promises in callbacks + cleanup --- client/events.lua | 11 +++++++++-- client/functions.lua | 33 +++++++++++++++++++++++++++------ server/events.lua | 14 +++++++++++--- server/functions.lua | 42 +++++++++++++++++++++++++++++------------- 4 files changed, 76 insertions(+), 24 deletions(-) diff --git a/client/events.lua b/client/events.lua index c172c16..67755aa 100644 --- a/client/events.lua +++ b/client/events.lua @@ -208,7 +208,9 @@ end) -- Client Callback RegisterNetEvent('QBCore:Client:TriggerClientCallback', function(name, ...) - QBCore.Functions.TriggerClientCallback(name, function(...) + if not QBCore.ClientCallbacks[name] then return end + + QBCore.ClientCallbacks[name](function(...) TriggerServerEvent('QBCore:Server:TriggerClientCallback', name, ...) end, ...) end) @@ -216,7 +218,12 @@ end) -- Server Callback RegisterNetEvent('QBCore:Client:TriggerCallback', function(name, ...) if QBCore.ServerCallbacks[name] then - QBCore.ServerCallbacks[name](...) + QBCore.ServerCallbacks[name].promise:resolve(...) + + if QBCore.ServerCallbacks[name].callback then + QBCore.ServerCallbacks[name].callback(...) + end + QBCore.ServerCallbacks[name] = nil end end) diff --git a/client/functions.lua b/client/functions.lua index 45034a5..1d3da23 100644 --- a/client/functions.lua +++ b/client/functions.lua @@ -6,14 +6,35 @@ function QBCore.Functions.CreateClientCallback(name, cb) QBCore.ClientCallbacks[name] = cb end -function QBCore.Functions.TriggerClientCallback(name, cb, ...) - if not QBCore.ClientCallbacks[name] then return end - QBCore.ClientCallbacks[name](cb, ...) -end +function QBCore.Functions.TriggerCallback(name, ...) + local cb = nil + local args = { ... } + + if type(args[1]) == "function" then + cb = args[1] + table.remove(args, 1) + elseif type(args[1]) == "table" then + local _, err = pcall(function() + args[1]["__cfx_functionReferenc"] = args[1]["__cfx_functionReferenc"] + end) + + if err and string.find(err, "Cannot index a funcref") then + cb = args[1] + table.remove(args, 1) + end + end + + QBCore.ServerCallbacks[name] = { + callback = cb, + promise = promise.new() + } -function QBCore.Functions.TriggerCallback(name, cb, ...) - QBCore.ServerCallbacks[name] = cb TriggerServerEvent('QBCore:Server:TriggerCallback', name, ...) + + if cb == nil then + Citizen.Await(QBCore.ServerCallbacks[name].promise) + return QBCore.ServerCallbacks[name].promise.value + end end function QBCore.Debug(resource, obj, depth) diff --git a/server/events.lua b/server/events.lua index 9311e80..00b0fa5 100644 --- a/server/events.lua +++ b/server/events.lua @@ -32,7 +32,7 @@ local databaseConnected, bansTableExists = readyFunction == nil, readyFunction = if readyFunction ~= nil then MySQL.ready(function() databaseConnected = true - + local DatabaseInfo = QBCore.Functions.GetDatabaseInfo() if not DatabaseInfo or not DatabaseInfo.exists then return end @@ -125,15 +125,23 @@ end) -- Client Callback RegisterNetEvent('QBCore:Server:TriggerClientCallback', function(name, ...) if QBCore.ClientCallbacks[name] then - QBCore.ClientCallbacks[name](...) + QBCore.ClientCallbacks[name].promise:resolve(...) + + if QBCore.ClientCallbacks[name].callback then + QBCore.ClientCallbacks[name].callback(...) + end + QBCore.ClientCallbacks[name] = nil end end) -- Server Callback RegisterNetEvent('QBCore:Server:TriggerCallback', function(name, ...) + if not QBCore.ServerCallbacks[name] then return end + local src = source - QBCore.Functions.TriggerCallback(name, src, function(...) + + QBCore.ServerCallbacks[name](src, function(...) TriggerClientEvent('QBCore:Client:TriggerCallback', src, name, ...) end, ...) end) diff --git a/server/functions.lua b/server/functions.lua index 9cfe78e..74b25bf 100644 --- a/server/functions.lua +++ b/server/functions.lua @@ -434,9 +434,35 @@ end ---@param source any ---@param cb function ---@param ... any -function QBCore.Functions.TriggerClientCallback(name, source, cb, ...) - QBCore.ClientCallbacks[name] = cb +function QBCore.Functions.TriggerClientCallback(name, source, ...) + local cb = nil + local args = { ... } + + if type(args[1]) == "function" then + cb = args[1] + table.remove(args, 1) + elseif type(args[1]) == "table" then + local _, err = pcall(function() + args[1]["__cfx_functionReferenc"] = args[1]["__cfx_functionReferenc"] + end) + + if err and string.find(err, "Cannot index a funcref") then + cb = args[1] + table.remove(args, 1) + end + end + + QBCore.ClientCallbacks[name] = { + callback = cb, + promise = promise.new() + } + TriggerClientEvent('QBCore:Client:TriggerClientCallback', source, name, ...) + + if cb == nil then + Citizen.Await(QBCore.ClientCallbacks[name].promise) + return QBCore.ClientCallbacks[name].promise.value + end end ---Create Server Callback @@ -446,16 +472,6 @@ function QBCore.Functions.CreateCallback(name, cb) QBCore.ServerCallbacks[name] = cb end ----Trigger Serv er Callback ----@param name string ----@param source any ----@param cb function ----@param ... any -function QBCore.Functions.TriggerCallback(name, source, cb, ...) - if not QBCore.ServerCallbacks[name] then return end - QBCore.ServerCallbacks[name](source, cb, ...) -end - -- Items ---Create a usable item @@ -475,7 +491,7 @@ function QBCore.Functions.CreateUseableItem(item, data) elseif type(data) == "function" then rawFunc = data end - + if rawFunc then QBCore.UsableItems[item] = { func = rawFunc, From 8660c98d4957e868fe37e18d0dcb325aa575de56 Mon Sep 17 00:00:00 2001 From: Zerio Date: Mon, 6 Jan 2025 21:41:53 +0100 Subject: [PATCH 16/26] fix: wrong args passed --- client/functions.lua | 2 +- server/functions.lua | 2 +- 2 files changed, 2 insertions(+), 2 deletions(-) diff --git a/client/functions.lua b/client/functions.lua index 1d3da23..f1ead70 100644 --- a/client/functions.lua +++ b/client/functions.lua @@ -29,7 +29,7 @@ function QBCore.Functions.TriggerCallback(name, ...) promise = promise.new() } - TriggerServerEvent('QBCore:Server:TriggerCallback', name, ...) + TriggerServerEvent('QBCore:Server:TriggerCallback', name, table.unpack(args)) if cb == nil then Citizen.Await(QBCore.ServerCallbacks[name].promise) diff --git a/server/functions.lua b/server/functions.lua index 74b25bf..7e4ac0e 100644 --- a/server/functions.lua +++ b/server/functions.lua @@ -457,7 +457,7 @@ function QBCore.Functions.TriggerClientCallback(name, source, ...) promise = promise.new() } - TriggerClientEvent('QBCore:Client:TriggerClientCallback', source, name, ...) + TriggerClientEvent('QBCore:Client:TriggerClientCallback', source, name, table.unpack(args)) if cb == nil then Citizen.Await(QBCore.ClientCallbacks[name].promise) From 8ab5f76bdfa6f917635e9817bf8ea2f9f85d1f77 Mon Sep 17 00:00:00 2001 From: Zerio Date: Tue, 7 Jan 2025 07:20:53 +0100 Subject: [PATCH 17/26] feat: simply funcref check --- client/functions.lua | 37 +++++++++++++++++++------------------ server/functions.lua | 40 ++++++++++++++++++++++------------------ shared/main.lua | 13 +++++++++++++ 3 files changed, 54 insertions(+), 36 deletions(-) diff --git a/client/functions.lua b/client/functions.lua index f1ead70..e3919ad 100644 --- a/client/functions.lua +++ b/client/functions.lua @@ -10,18 +10,9 @@ function QBCore.Functions.TriggerCallback(name, ...) local cb = nil local args = { ... } - if type(args[1]) == "function" then + if QBCore.Shared.IsFunction(args[1]) then cb = args[1] table.remove(args, 1) - elseif type(args[1]) == "table" then - local _, err = pcall(function() - args[1]["__cfx_functionReferenc"] = args[1]["__cfx_functionReferenc"] - end) - - if err and string.find(err, "Cannot index a funcref") then - cb = args[1] - table.remove(args, 1) - end end QBCore.ServerCallbacks[name] = { @@ -191,8 +182,12 @@ function QBCore.Functions.Notify(text, texttype, length, icon) SendNUIMessage(message) end -function QBCore.Functions.Progressbar(name, label, duration, useWhileDead, canCancel, disableControls, animation, prop, propTwo, onFinish, onCancel) - if GetResourceState('progressbar') ~= 'started' then error('progressbar needs to be started in order for QBCore.Functions.Progressbar to work') end +function QBCore.Functions.Progressbar(name, label, duration, useWhileDead, canCancel, disableControls, animation, prop, + propTwo, onFinish, onCancel) + if GetResourceState('progressbar') ~= 'started' then + error( + 'progressbar needs to be started in order for QBCore.Functions.Progressbar to work') + end exports['progressbar']:Progress({ name = name:lower(), duration = duration, @@ -977,7 +972,8 @@ function QBCore.Functions.StartParticleAtCoord(dict, ptName, looped, coords, rot SetPtfxAssetNextCall(dict) local particleHandle if looped then - particleHandle = StartParticleFxLoopedAtCoord(ptName, coords.x, coords.y, coords.z, rot.x, rot.y, rot.z, scale or 1.0) + particleHandle = StartParticleFxLoopedAtCoord(ptName, coords.x, coords.y, coords.z, rot.x, rot.y, rot.z, + scale or 1.0) if color then SetParticleFxLoopedColour(particleHandle, color.r, color.g, color.b, false) end @@ -996,7 +992,8 @@ function QBCore.Functions.StartParticleAtCoord(dict, ptName, looped, coords, rot return particleHandle end -function QBCore.Functions.StartParticleOnEntity(dict, ptName, looped, entity, bone, offset, rot, scale, alpha, color, evolution, duration) +function QBCore.Functions.StartParticleOnEntity(dict, ptName, looped, entity, bone, offset, rot, scale, alpha, color, + evolution, duration) QBCore.Functions.LoadParticleDictionary(dict) UseParticleFxAssetNextCall(dict) local particleHandle, boneID @@ -1007,9 +1004,11 @@ function QBCore.Functions.StartParticleOnEntity(dict, ptName, looped, entity, bo end if looped then if bone then - particleHandle = StartParticleFxLoopedOnEntityBone(ptName, entity, offset.x, offset.y, offset.z, rot.x, rot.y, rot.z, boneID, scale) + particleHandle = StartParticleFxLoopedOnEntityBone(ptName, entity, offset.x, offset.y, offset.z, rot.x, rot + .y, rot.z, boneID, scale) else - particleHandle = StartParticleFxLoopedOnEntity(ptName, entity, offset.x, offset.y, offset.z, rot.x, rot.y, rot.z, scale) + particleHandle = StartParticleFxLoopedOnEntity(ptName, entity, offset.x, offset.y, offset.z, rot.x, rot.y, + rot.z, scale) end if evolution then SetParticleFxLoopedEvolution(particleHandle, evolution.name, evolution.amount, false) @@ -1028,7 +1027,8 @@ function QBCore.Functions.StartParticleOnEntity(dict, ptName, looped, entity, bo SetParticleFxNonLoopedColour(color.r, color.g, color.b) end if bone then - StartParticleFxNonLoopedOnPedBone(ptName, entity, offset.x, offset.y, offset.z, rot.x, rot.y, rot.z, boneID, scale) + StartParticleFxNonLoopedOnPedBone(ptName, entity, offset.x, offset.y, offset.z, rot.x, rot.y, rot.z, boneID, + scale) else StartParticleFxNonLoopedOnEntity(ptName, entity, offset.x, offset.y, offset.z, rot.x, rot.y, rot.z, scale) end @@ -1092,7 +1092,8 @@ end function QBCore.Functions.GetGroundHash(entity) local coords = GetEntityCoords(entity) - local num = StartShapeTestCapsule(coords.x, coords.y, coords.z + 4, coords.x, coords.y, coords.z - 2.0, 1, 1, entity, 7) + local num = StartShapeTestCapsule(coords.x, coords.y, coords.z + 4, coords.x, coords.y, coords.z - 2.0, 1, 1, entity, + 7) local retval, success, endCoords, surfaceNormal, materialHash, entityHit = GetShapeTestResultEx(num) return materialHash, entityHit, surfaceNormal, endCoords, success, retval end diff --git a/server/functions.lua b/server/functions.lua index 7e4ac0e..1129c8b 100644 --- a/server/functions.lua +++ b/server/functions.lua @@ -399,26 +399,32 @@ function PaycheckInterval() if next(QBCore.Players) then for _, Player in pairs(QBCore.Players) do if Player then - local payment = QBShared.Jobs[Player.PlayerData.job.name]['grades'][tostring(Player.PlayerData.job.grade.level)].payment + local payment = QBShared.Jobs[Player.PlayerData.job.name]['grades'] + [tostring(Player.PlayerData.job.grade.level)].payment if not payment then payment = Player.PlayerData.job.payment end if Player.PlayerData.job and payment > 0 and (QBShared.Jobs[Player.PlayerData.job.name].offDutyPay or Player.PlayerData.job.onduty) then if QBCore.Config.Money.PayCheckSociety then local account = exports['qb-banking']:GetAccountBalance(Player.PlayerData.job.name) if account ~= 0 then -- Checks if player is employed by a society if account < payment then -- Checks if company has enough money to pay society - TriggerClientEvent('QBCore:Notify', Player.PlayerData.source, Lang:t('error.company_too_poor'), 'error') + TriggerClientEvent('QBCore:Notify', Player.PlayerData.source, + Lang:t('error.company_too_poor'), 'error') else Player.Functions.AddMoney('bank', payment, 'paycheck') - exports['qb-banking']:RemoveMoney(Player.PlayerData.job.name, payment, 'Employee Paycheck') - TriggerClientEvent('QBCore:Notify', Player.PlayerData.source, Lang:t('info.received_paycheck', { value = payment })) + exports['qb-banking']:RemoveMoney(Player.PlayerData.job.name, payment, + 'Employee Paycheck') + TriggerClientEvent('QBCore:Notify', Player.PlayerData.source, + Lang:t('info.received_paycheck', { value = payment })) end else Player.Functions.AddMoney('bank', payment, 'paycheck') - TriggerClientEvent('QBCore:Notify', Player.PlayerData.source, Lang:t('info.received_paycheck', { value = payment })) + TriggerClientEvent('QBCore:Notify', Player.PlayerData.source, + Lang:t('info.received_paycheck', { value = payment })) end else Player.Functions.AddMoney('bank', payment, 'paycheck') - TriggerClientEvent('QBCore:Notify', Player.PlayerData.source, Lang:t('info.received_paycheck', { value = payment })) + TriggerClientEvent('QBCore:Notify', Player.PlayerData.source, + Lang:t('info.received_paycheck', { value = payment })) end end end @@ -438,20 +444,12 @@ function QBCore.Functions.TriggerClientCallback(name, source, ...) local cb = nil local args = { ... } - if type(args[1]) == "function" then + if QBCore.Shared.IsFunction(args[1]) then cb = args[1] table.remove(args, 1) - elseif type(args[1]) == "table" then - local _, err = pcall(function() - args[1]["__cfx_functionReferenc"] = args[1]["__cfx_functionReferenc"] - end) - - if err and string.find(err, "Cannot index a funcref") then - cb = args[1] - table.remove(args, 1) - end end + QBCore.ClientCallbacks[name] = { callback = cb, promise = promise.new() @@ -651,7 +649,12 @@ function QBCore.Functions.IsPlayerBanned(source) if not result then return false end if os.time() < result.expire then local timeTable = os.date('*t', tonumber(result.expire)) - return true, 'You have been banned from the server:\n' .. result.reason .. '\nYour ban expires ' .. timeTable.day .. '/' .. timeTable.month .. '/' .. timeTable.year .. ' ' .. timeTable.hour .. ':' .. timeTable.min .. '\n' + return true, + 'You have been banned from the server:\n' .. + result.reason .. + '\nYour ban expires ' .. + timeTable.day .. + '/' .. timeTable.month .. '/' .. timeTable.year .. ' ' .. timeTable.hour .. ':' .. timeTable.min .. '\n' else MySQL.query('DELETE FROM bans WHERE id = ?', { result.id }) end @@ -732,7 +735,8 @@ function QBCore.Functions.PrepForSQL(source, data, pattern) local player = QBCore.Functions.GetPlayer(src) local result = string.match(data, pattern) if not result or string.len(result) ~= string.len(data) then - TriggerEvent('qb-log:server:CreateLog', 'anticheat', 'SQL Exploit Attempted', 'red', string.format('%s attempted to exploit SQL!', player.PlayerData.license)) + TriggerEvent('qb-log:server:CreateLog', 'anticheat', 'SQL Exploit Attempted', 'red', + string.format('%s attempted to exploit SQL!', player.PlayerData.license)) return false end return true diff --git a/shared/main.lua b/shared/main.lua index d01b93c..77dc265 100644 --- a/shared/main.lua +++ b/shared/main.lua @@ -68,6 +68,19 @@ function QBShared.ChangeVehicleExtra(vehicle, extra, enable) end end +function QBShared.IsFunction(value) + if type(value) == 'table' then + local success = pcall(function() + -- we just need to check if the table is indexable or not, this will simply return the error "cannot index a funcref" + return value.__cfx_functionReference + end) + + return success + end + + return type(value) == 'function' +end + function QBShared.SetDefaultVehicleExtras(vehicle, config) -- Clear Extras for i = 1, 20 do From d08d7bbebaa3c7741f52d52a2244d74d134d2096 Mon Sep 17 00:00:00 2001 From: Zerio Date: Tue, 7 Jan 2025 07:21:50 +0100 Subject: [PATCH 18/26] chore: remove accidental automatic format changes --- client/functions.lua | 26 ++++++++------------------ server/functions.lua | 29 ++++++++--------------------- 2 files changed, 16 insertions(+), 39 deletions(-) diff --git a/client/functions.lua b/client/functions.lua index e3919ad..8c03183 100644 --- a/client/functions.lua +++ b/client/functions.lua @@ -182,12 +182,8 @@ function QBCore.Functions.Notify(text, texttype, length, icon) SendNUIMessage(message) end -function QBCore.Functions.Progressbar(name, label, duration, useWhileDead, canCancel, disableControls, animation, prop, - propTwo, onFinish, onCancel) - if GetResourceState('progressbar') ~= 'started' then - error( - 'progressbar needs to be started in order for QBCore.Functions.Progressbar to work') - end +function QBCore.Functions.Progressbar(name, label, duration, useWhileDead, canCancel, disableControls, animation, prop, propTwo, onFinish, onCancel) + if GetResourceState('progressbar') ~= 'started' then error('progressbar needs to be started in order for QBCore.Functions.Progressbar to work') end exports['progressbar']:Progress({ name = name:lower(), duration = duration, @@ -972,8 +968,7 @@ function QBCore.Functions.StartParticleAtCoord(dict, ptName, looped, coords, rot SetPtfxAssetNextCall(dict) local particleHandle if looped then - particleHandle = StartParticleFxLoopedAtCoord(ptName, coords.x, coords.y, coords.z, rot.x, rot.y, rot.z, - scale or 1.0) + particleHandle = StartParticleFxLoopedAtCoord(ptName, coords.x, coords.y, coords.z, rot.x, rot.y, rot.z, scale or 1.0) if color then SetParticleFxLoopedColour(particleHandle, color.r, color.g, color.b, false) end @@ -992,8 +987,7 @@ function QBCore.Functions.StartParticleAtCoord(dict, ptName, looped, coords, rot return particleHandle end -function QBCore.Functions.StartParticleOnEntity(dict, ptName, looped, entity, bone, offset, rot, scale, alpha, color, - evolution, duration) +function QBCore.Functions.StartParticleOnEntity(dict, ptName, looped, entity, bone, offset, rot, scale, alpha, color, evolution, duration) QBCore.Functions.LoadParticleDictionary(dict) UseParticleFxAssetNextCall(dict) local particleHandle, boneID @@ -1004,11 +998,9 @@ function QBCore.Functions.StartParticleOnEntity(dict, ptName, looped, entity, bo end if looped then if bone then - particleHandle = StartParticleFxLoopedOnEntityBone(ptName, entity, offset.x, offset.y, offset.z, rot.x, rot - .y, rot.z, boneID, scale) + particleHandle = StartParticleFxLoopedOnEntityBone(ptName, entity, offset.x, offset.y, offset.z, rot.x, rot.y, rot.z, boneID, scale) else - particleHandle = StartParticleFxLoopedOnEntity(ptName, entity, offset.x, offset.y, offset.z, rot.x, rot.y, - rot.z, scale) + particleHandle = StartParticleFxLoopedOnEntity(ptName, entity, offset.x, offset.y, offset.z, rot.x, rot.y, rot.z, scale) end if evolution then SetParticleFxLoopedEvolution(particleHandle, evolution.name, evolution.amount, false) @@ -1027,8 +1019,7 @@ function QBCore.Functions.StartParticleOnEntity(dict, ptName, looped, entity, bo SetParticleFxNonLoopedColour(color.r, color.g, color.b) end if bone then - StartParticleFxNonLoopedOnPedBone(ptName, entity, offset.x, offset.y, offset.z, rot.x, rot.y, rot.z, boneID, - scale) + StartParticleFxNonLoopedOnPedBone(ptName, entity, offset.x, offset.y, offset.z, rot.x, rot.y, rot.z, boneID, scale) else StartParticleFxNonLoopedOnEntity(ptName, entity, offset.x, offset.y, offset.z, rot.x, rot.y, rot.z, scale) end @@ -1092,8 +1083,7 @@ end function QBCore.Functions.GetGroundHash(entity) local coords = GetEntityCoords(entity) - local num = StartShapeTestCapsule(coords.x, coords.y, coords.z + 4, coords.x, coords.y, coords.z - 2.0, 1, 1, entity, - 7) + local num = StartShapeTestCapsule(coords.x, coords.y, coords.z + 4, coords.x, coords.y, coords.z - 2.0, 1, 1, entity, 7) local retval, success, endCoords, surfaceNormal, materialHash, entityHit = GetShapeTestResultEx(num) return materialHash, entityHit, surfaceNormal, endCoords, success, retval end diff --git a/server/functions.lua b/server/functions.lua index 1129c8b..d9bfc57 100644 --- a/server/functions.lua +++ b/server/functions.lua @@ -399,32 +399,26 @@ function PaycheckInterval() if next(QBCore.Players) then for _, Player in pairs(QBCore.Players) do if Player then - local payment = QBShared.Jobs[Player.PlayerData.job.name]['grades'] - [tostring(Player.PlayerData.job.grade.level)].payment + local payment = QBShared.Jobs[Player.PlayerData.job.name]['grades'][tostring(Player.PlayerData.job.grade.level)].payment if not payment then payment = Player.PlayerData.job.payment end if Player.PlayerData.job and payment > 0 and (QBShared.Jobs[Player.PlayerData.job.name].offDutyPay or Player.PlayerData.job.onduty) then if QBCore.Config.Money.PayCheckSociety then local account = exports['qb-banking']:GetAccountBalance(Player.PlayerData.job.name) if account ~= 0 then -- Checks if player is employed by a society if account < payment then -- Checks if company has enough money to pay society - TriggerClientEvent('QBCore:Notify', Player.PlayerData.source, - Lang:t('error.company_too_poor'), 'error') + TriggerClientEvent('QBCore:Notify', Player.PlayerData.source, Lang:t('error.company_too_poor'), 'error') else Player.Functions.AddMoney('bank', payment, 'paycheck') - exports['qb-banking']:RemoveMoney(Player.PlayerData.job.name, payment, - 'Employee Paycheck') - TriggerClientEvent('QBCore:Notify', Player.PlayerData.source, - Lang:t('info.received_paycheck', { value = payment })) + exports['qb-banking']:RemoveMoney(Player.PlayerData.job.name, payment, 'Employee Paycheck') + TriggerClientEvent('QBCore:Notify', Player.PlayerData.source, Lang:t('info.received_paycheck', { value = payment })) end else Player.Functions.AddMoney('bank', payment, 'paycheck') - TriggerClientEvent('QBCore:Notify', Player.PlayerData.source, - Lang:t('info.received_paycheck', { value = payment })) + TriggerClientEvent('QBCore:Notify', Player.PlayerData.source, Lang:t('info.received_paycheck', { value = payment })) end else Player.Functions.AddMoney('bank', payment, 'paycheck') - TriggerClientEvent('QBCore:Notify', Player.PlayerData.source, - Lang:t('info.received_paycheck', { value = payment })) + TriggerClientEvent('QBCore:Notify', Player.PlayerData.source, Lang:t('info.received_paycheck', { value = payment })) end end end @@ -449,7 +443,6 @@ function QBCore.Functions.TriggerClientCallback(name, source, ...) table.remove(args, 1) end - QBCore.ClientCallbacks[name] = { callback = cb, promise = promise.new() @@ -649,12 +642,7 @@ function QBCore.Functions.IsPlayerBanned(source) if not result then return false end if os.time() < result.expire then local timeTable = os.date('*t', tonumber(result.expire)) - return true, - 'You have been banned from the server:\n' .. - result.reason .. - '\nYour ban expires ' .. - timeTable.day .. - '/' .. timeTable.month .. '/' .. timeTable.year .. ' ' .. timeTable.hour .. ':' .. timeTable.min .. '\n' + return true, 'You have been banned from the server:\n' .. result.reason .. '\nYour ban expires ' .. timeTable.day .. '/' .. timeTable.month .. '/' .. timeTable.year .. ' ' .. timeTable.hour .. ':' .. timeTable.min .. '\n' else MySQL.query('DELETE FROM bans WHERE id = ?', { result.id }) end @@ -735,8 +723,7 @@ function QBCore.Functions.PrepForSQL(source, data, pattern) local player = QBCore.Functions.GetPlayer(src) local result = string.match(data, pattern) if not result or string.len(result) ~= string.len(data) then - TriggerEvent('qb-log:server:CreateLog', 'anticheat', 'SQL Exploit Attempted', 'red', - string.format('%s attempted to exploit SQL!', player.PlayerData.license)) + TriggerEvent('qb-log:server:CreateLog', 'anticheat', 'SQL Exploit Attempted', 'red', string.format('%s attempted to exploit SQL!', player.PlayerData.license)) return false end return true From 369f15bd4c1cd6643019d7a74fc60e4338799ee2 Mon Sep 17 00:00:00 2001 From: Zerio Date: Tue, 7 Jan 2025 07:40:43 +0100 Subject: [PATCH 19/26] feat: further simplify of funcref check --- shared/main.lua | 7 +------ 1 file changed, 1 insertion(+), 6 deletions(-) diff --git a/shared/main.lua b/shared/main.lua index 77dc265..2863b35 100644 --- a/shared/main.lua +++ b/shared/main.lua @@ -70,12 +70,7 @@ end function QBShared.IsFunction(value) if type(value) == 'table' then - local success = pcall(function() - -- we just need to check if the table is indexable or not, this will simply return the error "cannot index a funcref" - return value.__cfx_functionReference - end) - - return success + return value.__cfx_functionReference ~= nil and type(value.__cfx_functionReference) == "string" end return type(value) == 'function' From 54261ecb4e59270ba3b6f8e5716970bfe9eacab9 Mon Sep 17 00:00:00 2001 From: Cocodrulo <142546774+Cocodrulo@users.noreply.github.com> Date: Wed, 8 Jan 2025 13:25:04 +0100 Subject: [PATCH 20/26] Add function to retrieve player's full name from character info --- client/functions.lua | 5 +++++ 1 file changed, 5 insertions(+) diff --git a/client/functions.lua b/client/functions.lua index 45034a5..b329f24 100644 --- a/client/functions.lua +++ b/client/functions.lua @@ -36,6 +36,11 @@ function QBCore.Functions.HasItem(items, amount) return exports['qb-inventory']:HasItem(items, amount) end +function exports.Functions.GetName() + local charinfo = QBCore.PlayerData.charinfo + return charinfo.firstname .. ' ' .. charinfo.lastname +end + ---@param entity number - The entity to look at ---@param timeout number - The time in milliseconds before the function times out ---@param speed number - The speed at which the entity should turn From e288b742c87f3403c7bdeb3aaa60a3a88d9b2d2a Mon Sep 17 00:00:00 2001 From: Cocodrulo <142546774+Cocodrulo@users.noreply.github.com> Date: Wed, 8 Jan 2025 13:25:07 +0100 Subject: [PATCH 21/26] Add function to retrieve player's full name from character data --- server/player.lua | 5 +++++ 1 file changed, 5 insertions(+) diff --git a/server/player.lua b/server/player.lua index cbc5032..4f73c0d 100644 --- a/server/player.lua +++ b/server/player.lua @@ -253,6 +253,11 @@ function QBCore.Player.CreatePlayer(PlayerData, Offline) return QBCore.Functions.HasItem(self.PlayerData.source, items, amount) end + function self.Functions.GetName() + local charinfo = self.PlayerData.charinfo + return charinfo.firstname .. ' ' .. charinfo.lastname + end + function self.Functions.SetJobDuty(onDuty) self.PlayerData.job.onduty = not not onDuty TriggerEvent('QBCore:Server:OnJobUpdate', self.PlayerData.source, self.PlayerData.job) From f553fe3f260168b47435676b12f344bd9ee47c08 Mon Sep 17 00:00:00 2001 From: Cocodrulo <142546774+Cocodrulo@users.noreply.github.com> Date: Wed, 8 Jan 2025 13:27:48 +0100 Subject: [PATCH 22/26] Add function to retrieve full character name --- client/functions.lua | 2 ++ 1 file changed, 2 insertions(+) diff --git a/client/functions.lua b/client/functions.lua index b329f24..e99ece5 100644 --- a/client/functions.lua +++ b/client/functions.lua @@ -36,6 +36,8 @@ function QBCore.Functions.HasItem(items, amount) return exports['qb-inventory']:HasItem(items, amount) end +---Returns the full character name +---@return string function exports.Functions.GetName() local charinfo = QBCore.PlayerData.charinfo return charinfo.firstname .. ' ' .. charinfo.lastname From c3ad04d0c9d3104ce1ebb7d774fa695dc6a20b31 Mon Sep 17 00:00:00 2001 From: Cocodrulo <142546774+Cocodrulo@users.noreply.github.com> Date: Wed, 8 Jan 2025 13:31:03 +0100 Subject: [PATCH 23/26] fix: Refactor GetName function to use QBCore namespace --- client/functions.lua | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/client/functions.lua b/client/functions.lua index e99ece5..5ea6151 100644 --- a/client/functions.lua +++ b/client/functions.lua @@ -38,7 +38,7 @@ end ---Returns the full character name ---@return string -function exports.Functions.GetName() +function QBCore.Functions.GetName() local charinfo = QBCore.PlayerData.charinfo return charinfo.firstname .. ' ' .. charinfo.lastname end From ba658d99a09a0ed8d8ceb4f29b220657295061ae Mon Sep 17 00:00:00 2001 From: Christian J Bennett <58433059+ChristianBDev@users.noreply.github.com> Date: Tue, 21 Jan 2025 12:04:58 -0600 Subject: [PATCH 24/26] Fixed the hasKeys Export to return the value true of HasKeys --- client/events.lua | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/client/events.lua b/client/events.lua index 67755aa..f08e019 100644 --- a/client/events.lua +++ b/client/events.lua @@ -164,7 +164,7 @@ RegisterNetEvent('QBCore:Client:VehicleInfo', function(info) local hasKeys = true if GetResourceState('qb-vehiclekeys') == 'started' then - hasKeys = exports['qb-vehiclekeys']:HasKeys() + hasKeys = exports['qb-vehiclekeys']:HasKeys(plate) end local data = { From e90fa911021597ccafe420b125cef54b90ff5a05 Mon Sep 17 00:00:00 2001 From: Borre <103928083+Borreke0@users.noreply.github.com> Date: Fri, 24 Jan 2025 19:27:01 +0100 Subject: [PATCH 25/26] TP with heading support Added support for the heading argument when using the /tp command. --- server/commands.lua | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/server/commands.lua b/server/commands.lua index 5f90980..368736f 100644 --- a/server/commands.lua +++ b/server/commands.lua @@ -104,8 +104,9 @@ QBCore.Commands.Add('tp', Lang:t('command.tp.help'), { { name = Lang:t('command. local x = tonumber((args[1]:gsub(',', ''))) + .0 local y = tonumber((args[2]:gsub(',', ''))) + .0 local z = tonumber((args[3]:gsub(',', ''))) + .0 + local heading = args[4] and tonumber((args[4]:gsub(',', ''))) + .0 or false if x ~= 0 and y ~= 0 and z ~= 0 then - TriggerClientEvent('QBCore:Command:TeleportToCoords', source, x, y, z) + TriggerClientEvent('QBCore:Command:TeleportToCoords', source, x, y, z, heading) else TriggerClientEvent('QBCore:Notify', source, Lang:t('error.wrong_format'), 'error') end From 9adb33b970f16c92aaa2fe6d341ec23a716e0de6 Mon Sep 17 00:00:00 2001 From: Kakarot <57848836+GhzGarage@users.noreply.github.com> Date: Sat, 25 Jan 2025 00:36:31 -0600 Subject: [PATCH 26/26] Core object filtering + exported functions/data Maintains backwards compatibility and allows users to only get what they need from the core instead of importing it all --- client/functions.lua | 9 ++++++ client/main.lua | 48 ++++++++++++++++++++++++++++---- fxmanifest.lua | 2 +- server/functions.lua | 66 ++++++++++++++++++++++++-------------------- server/main.lua | 48 ++++++++++++++++++++++++++++---- 5 files changed, 130 insertions(+), 43 deletions(-) diff --git a/client/functions.lua b/client/functions.lua index 737b12c..f6bca00 100644 --- a/client/functions.lua +++ b/client/functions.lua @@ -1094,3 +1094,12 @@ function QBCore.Functions.GetGroundHash(entity) local retval, success, endCoords, surfaceNormal, materialHash, entityHit = GetShapeTestResultEx(num) return materialHash, entityHit, surfaceNormal, endCoords, success, retval end + +for functionName, func in pairs(QBCore.Functions) do + if type(func) == 'function' then + exports(functionName, func) + end +end + +-- Access a specific function directly: +-- exports['qb-core']:Notify('Hello Player!') diff --git a/client/main.lua b/client/main.lua index 7407a6d..05d3b68 100644 --- a/client/main.lua +++ b/client/main.lua @@ -5,10 +5,46 @@ QBCore.Shared = QBShared QBCore.ClientCallbacks = {} QBCore.ServerCallbacks = {} -exports('GetCoreObject', function() - return QBCore -end) +-- Get the full QBCore object (default behavior): +-- local QBCore = GetCoreObject() --- To use this export in a script instead of manifest method --- Just put this line of code below at the very top of the script --- local QBCore = exports['qb-core']:GetCoreObject() +-- Get only specific parts of QBCore: +-- local QBCore = GetCoreObject({'Players', 'Config'}) + +local function GetCoreObject(filters) + if not filters then return QBCore end + local results = {} + for i = 1, #filters do + local key = filters[i] + if QBCore[key] then + results[key] = QBCore[key] + end + end + return results +end +exports('GetCoreObject', GetCoreObject) + +local function GetSharedItems() + return QBShared.Items +end +exports('GetSharedItems', GetSharedItems) + +local function GetSharedVehicles() + return QBShared.Vehicles +end +exports('GetSharedVehicles', GetSharedVehicles) + +local function GetSharedWeapons() + return QBShared.Weapons +end +exports('GetSharedWeapons', GetSharedWeapons) + +local function GetSharedJobs() + return QBShared.Jobs +end +exports('GetSharedJobs', GetSharedJobs) + +local function GetSharedGangs() + return QBShared.Gangs +end +exports('GetSharedGangs', GetSharedGangs) diff --git a/fxmanifest.lua b/fxmanifest.lua index bc0da07..924a561 100644 --- a/fxmanifest.lua +++ b/fxmanifest.lua @@ -3,7 +3,7 @@ game 'gta5' lua54 'yes' author 'Kakarot' description 'Core resource for the framework, contains all the core functionality and features' -version '1.2.6' +version '1.3.0' shared_scripts { 'config.lua', diff --git a/server/functions.lua b/server/functions.lua index d9bfc57..8f81093 100644 --- a/server/functions.lua +++ b/server/functions.lua @@ -394,33 +394,30 @@ function QBCore.Functions.CreateVehicle(source, model, vehtype, coords, warp) return veh end ----Paychecks (standalone - don't touch) function PaycheckInterval() - if next(QBCore.Players) then - for _, Player in pairs(QBCore.Players) do - if Player then - local payment = QBShared.Jobs[Player.PlayerData.job.name]['grades'][tostring(Player.PlayerData.job.grade.level)].payment - if not payment then payment = Player.PlayerData.job.payment end - if Player.PlayerData.job and payment > 0 and (QBShared.Jobs[Player.PlayerData.job.name].offDutyPay or Player.PlayerData.job.onduty) then - if QBCore.Config.Money.PayCheckSociety then - local account = exports['qb-banking']:GetAccountBalance(Player.PlayerData.job.name) - if account ~= 0 then -- Checks if player is employed by a society - if account < payment then -- Checks if company has enough money to pay society - TriggerClientEvent('QBCore:Notify', Player.PlayerData.source, Lang:t('error.company_too_poor'), 'error') - else - Player.Functions.AddMoney('bank', payment, 'paycheck') - exports['qb-banking']:RemoveMoney(Player.PlayerData.job.name, payment, 'Employee Paycheck') - TriggerClientEvent('QBCore:Notify', Player.PlayerData.source, Lang:t('info.received_paycheck', { value = payment })) - end - else - Player.Functions.AddMoney('bank', payment, 'paycheck') - TriggerClientEvent('QBCore:Notify', Player.PlayerData.source, Lang:t('info.received_paycheck', { value = payment })) - end + if not next(QBCore.Players) then return end + for _, Player in pairs(QBCore.Players) do + if not Player then return end + local payment = QBShared.Jobs[Player.PlayerData.job.name]['grades'][tostring(Player.PlayerData.job.grade.level)].payment + if not payment then payment = Player.PlayerData.job.payment end + if Player.PlayerData.job and payment > 0 and (QBShared.Jobs[Player.PlayerData.job.name].offDutyPay or Player.PlayerData.job.onduty) then + if QBCore.Config.Money.PayCheckSociety then + local account = exports['qb-banking']:GetAccountBalance(Player.PlayerData.job.name) + if account ~= 0 then + if account < payment then + TriggerClientEvent('QBCore:Notify', Player.PlayerData.source, Lang:t('error.company_too_poor'), 'error') else Player.Functions.AddMoney('bank', payment, 'paycheck') + exports['qb-banking']:RemoveMoney(Player.PlayerData.job.name, payment, 'Employee Paycheck') TriggerClientEvent('QBCore:Notify', Player.PlayerData.source, Lang:t('info.received_paycheck', { value = payment })) end + else + Player.Functions.AddMoney('bank', payment, 'paycheck') + TriggerClientEvent('QBCore:Notify', Player.PlayerData.source, Lang:t('info.received_paycheck', { value = payment })) end + else + Player.Functions.AddMoney('bank', payment, 'paycheck') + TriggerClientEvent('QBCore:Notify', Player.PlayerData.source, Lang:t('info.received_paycheck', { value = payment })) end end end @@ -471,7 +468,7 @@ end function QBCore.Functions.CreateUseableItem(item, data) local rawFunc = nil - if type(data) == "table" then + if type(data) == 'table' then if rawget(data, '__cfx_functionReference') then rawFunc = data elseif data.cb and rawget(data.cb, '__cfx_functionReference') then @@ -479,7 +476,7 @@ function QBCore.Functions.CreateUseableItem(item, data) elseif data.callback and rawget(data.callback, '__cfx_functionReference') then rawFunc = data.callback end - elseif type(data) == "function" then + elseif type(data) == 'function' then rawFunc = data end @@ -654,23 +651,23 @@ end function QBCore.Functions.GetDatabaseInfo() local details = { exists = false, - database = "", + database = '', } - local connectionString = GetConvar("mysql_connection_string", "") + local connectionString = GetConvar('mysql_connection_string', '') - if connectionString == "" then + if connectionString == '' then return details - elseif connectionString:find("mysql://") then + elseif connectionString:find('mysql://') then connectionString = connectionString:sub(9, -1) - details.database = connectionString:sub(connectionString:find("/") + 1, -1):gsub("[%?]+[%w%p]*$", "") + details.database = connectionString:sub(connectionString:find('/') + 1, -1):gsub('[%?]+[%w%p]*$', '') details.exists = true return details else - connectionString = { string.strsplit(";", connectionString) } + connectionString = { string.strsplit(';', connectionString) } for i = 1, #connectionString do local v = connectionString[i] - if v:match("database") then + if v:match('database') then details.database = v:sub(10, #v) details.exists = true return details @@ -728,3 +725,12 @@ function QBCore.Functions.PrepForSQL(source, data, pattern) end return true end + +for functionName, func in pairs(QBCore.Functions) do + if type(func) == 'function' then + exports(functionName, func) + end +end + +-- Access a specific function directly: +-- exports['qb-core']:Notify(source, 'Hello Player!') diff --git a/server/main.lua b/server/main.lua index 368dc05..d6228e5 100644 --- a/server/main.lua +++ b/server/main.lua @@ -4,10 +4,46 @@ QBCore.Shared = QBShared QBCore.ClientCallbacks = {} QBCore.ServerCallbacks = {} -exports('GetCoreObject', function() - return QBCore -end) +-- Get the full QBCore object (default behavior): +-- local QBCore = GetCoreObject() --- To use this export in a script instead of manifest method --- Just put this line of code below at the very top of the script --- local QBCore = exports['qb-core']:GetCoreObject() +-- Get only specific parts of QBCore: +-- local QBCore = GetCoreObject({'Players', 'Config'}) + +local function GetCoreObject(filters) + if not filters then return QBCore end + local results = {} + for i = 1, #filters do + local key = filters[i] + if QBCore[key] then + results[key] = QBCore[key] + end + end + return results +end +exports('GetCoreObject', GetCoreObject) + +local function GetSharedItems() + return QBShared.Items +end +exports('GetSharedItems', GetSharedItems) + +local function GetSharedVehicles() + return QBShared.Vehicles +end +exports('GetSharedVehicles', GetSharedVehicles) + +local function GetSharedWeapons() + return QBShared.Weapons +end +exports('GetSharedWeapons', GetSharedWeapons) + +local function GetSharedJobs() + return QBShared.Jobs +end +exports('GetSharedJobs', GetSharedJobs) + +local function GetSharedGangs() + return QBShared.Gangs +end +exports('GetSharedGangs', GetSharedGangs)